Urthar Posted August 11, 2015 So I've been messing around with a hardware shader to recreate the Quake sky effect, but I've run into a problem with these black lines at the edges of the texture: This is a JPEG of the base texture, the white is actually zero alpha in the PNG: And this is the shader I wrote: uniform float timer; vec4 Process(vec4 color) { // get uv coordinates vec2 uppersky = gl_TexCoord[0].st; vec2 lowersky = gl_TexCoord[0].st; // scroll upper sky uppersky.x += timer * 0.1; uppersky.y += timer * 0.1; // uppersky is left half of texture uppersky.x = (uppersky.x - floor(uppersky.x)) / 2.0; uppersky.y = (uppersky.y - floor(uppersky.y)); // scroll lowersky lowersky.x += timer * 0.2; lowersky.y += timer * 0.2; // lowersky is right half of texture lowersky.x = ((lowersky.x - floor(lowersky.x)) + 1.0) / 2.0; lowersky.y = (lowersky.y - floor(lowersky.y)); // get texel for updated uv coordinates vec4 lowerskyTexel = getTexel(lowersky); vec4 upperskyTexel = getTexel(uppersky); // Draw either the lowersky, or the uppersky if(lowerskyTexel.a > 0) return lowerskyTexel * color; else return upperskyTexel * color; } Any ideas on how to get rid of the black lines? 0 Quote Share this post Link to post
Graf Zahl Posted August 11, 2015 You have to account for texture filtering so both halves need some space to wrap around. My suggestion would be to make the texture twice as wide with both halves repeating once and then only use the middle parts of both halves. 0 Quote Share this post Link to post
Urthar Posted August 11, 2015 Yeah anisotropic filtering seemed to be the main culprit. The effect disappered when I switched it off: With 'max' filtering, I got additional horizontal black lines, and a nasty alpha blend: Thanks for the quick advice, I'll try tiling the texure within a border, and see if I can get a more robust result. 0 Quote Share this post Link to post
Urthar Posted August 11, 2015 I put a 32 pixel wide border around each sky, creating a 384x192 texture, but still encountered some artifacts: No filtering and Linear filtering worked ok: No filtering with Nearest and Linear mip produced some artifacts: Likewise Bilinear and Trilinear filtering: Anisotropic produced increasing artifacts at higher levels, this image is at 16: The HQ Resize option, seemed to work fine with Scale4x, but HQ4x produced minor alpha blending artifacts. 0 Quote Share this post Link to post
Urthar Posted August 11, 2015 fabian said:Cool, how does it look in motion? The scrolling itself works fine. I made a little 256 radius hemipshere and placed a Skybox Viewpoint in it to mimic Quake's distortion effect. 0 Quote Share this post Link to post
boris Posted August 11, 2015 Urthar said:I put a 32 pixel wide border around each sky, creating a 384x192 texture, but still encountered some artifacts: You could try to tile the original textures into the borders (and change the shader to not touch the borders. Or something like that. 0 Quote Share this post Link to post
Ribbiks Posted August 11, 2015 Urthar said:No filtering and Linear filtering worked ok: damn this looks cool. These are stock quake textures? I should really give that game another chance 0 Quote Share this post Link to post
Graf Zahl Posted August 11, 2015 Urthar said:I put a 32 pixel wide border around each sky, creating a 384x192 texture, but still encountered some artifacts: Are you sure you properly changed the texture coordinate calculations for the altered texture? You have to make sure that yo never get to the borders in the x-direction because that's where the transparent pixels get accessed creating these artifacts. 0 Quote Share this post Link to post
Urthar Posted August 11, 2015 Yeah, updated the shader:uniform float timer; vec4 Process(vec4 color) { // get uv coordinates vec2 uppersky = gl_TexCoord[0].st; vec2 lowersky = gl_TexCoord[0].st; // scroll upper sky uppersky.x += timer * 0.05; uppersky.y += timer * 0.05; // uppersky is left half of texture uppersky.x = ((uppersky.x - floor(uppersky.x)) / 3.0) + (1.0 / 12.0); uppersky.y = ((uppersky.y - floor(uppersky.y)) / 1.5) + (1.0 / 6.0); // scroll lowersky lowersky.x += timer * 0.1; lowersky.y += timer * 0.1; // lowersky is right half of texture lowersky.x = ((lowersky.x - floor(lowersky.x)) / 3.0) + (7.0 / 12.0); lowersky.y = ((lowersky.y - floor(lowersky.y)) / 1.5) + (1.0 / 6.0); // get texel for updated uv coordinates vec4 lowerskyTexel = getTexel(lowersky); vec4 upperskyTexel = getTexel(uppersky); // Draw either the lowersky, or the uppersky if(lowerskyTexel.a > 0) return lowerskyTexel * color; else return upperskyTexel * color; } The tiling itself basically works fine. I'll try a straight up 512x256 variant next and see if powers of 2 makes the difference. 0 Quote Share this post Link to post
Graf Zahl Posted August 11, 2015 I have no means to do quick tests but I believe that you somehow need to get the coordinate back into the [0..1] range after adding the timer. You should also blend the colors if the alpha at the end is neither 0 nor 1 so that filtered edges of the upper texture get displayed correctly (use the 'mix' function for that.) 0 Quote Share this post Link to post
Urthar Posted August 11, 2015 boris said:You could try to tile the original textures into the borders (and change the shader to not touch the borders. Or something like that. Yeah, that's basically what I did. Ribbiks said:damn this looks cool. These are stock quake textures? I should really give that game another chance They are the stock textures converted to 32bit PNGs, with a few resizes to match q1tex.wad. GZDoom seems fine with non powers of 2 though, so I may switch back to the original texture sizes. 0 Quote Share this post Link to post
Graf Zahl Posted August 11, 2015 Urthar said:GZDoom seems fine with non powers of 2 though. All GL 2.x+ hardware can deal with arbitrary texture sizes, and anything older is no longer supported by the engine, so yes, it's fine to use any texture size you like. 0 Quote Share this post Link to post
Urthar Posted August 11, 2015 Replacing the IF THEN statement with;return color * mix(upperskyTexel, lowerskyTexel, lowerskyTexel.a); didn't change any behaviour. I noticed the texels themselves look ok, the black lines seem resolution dependant, at 1920x1080 they're barely visible single pixel wide lines. 0 Quote Share this post Link to post
Graf Zahl Posted August 12, 2015 That doesn't surprise me, that only affects the edges of the upper layer. Your real issue here is that at some point your texture coordinates reach the edges, you have to ensure they stay within the part of the texture that's ok to use. Can you put it all together into a small demo project so I can check it myself? 0 Quote Share this post Link to post
Urthar Posted August 12, 2015 Sure, I'll send you a PM with the link. In the mean time, I'll try using a very low but non-zero alpha and see if I can force the PNG to store the background sky colour instead of black. 0 Quote Share this post Link to post
andrewj Posted August 12, 2015 Looks a bit like what happens when you have a T-junction (to use the Quake term), e.g. geometry such as a rectangle on top and two squares underneath it and the polygon for the rectangle on top does not include the vertex shared between the two squares (when drawn), hence fragment drawing can produce gaps along that large edge. I think Nvidia cards are better at handling that situation than other brands. 0 Quote Share this post Link to post
boris Posted August 12, 2015 With proper tiling and a 32 pixel border around each actual texture it should look something like this: But you don't want to use the full texture, but only those parts: So you'll have to change your shader to keep the texture coordinates inside the squares. 0 Quote Share this post Link to post
Urthar Posted August 12, 2015 That's pretty much what I did Boris. (I ended up with a 64 pixel offset, but it's basically the same.) Tried a 512x256 version with non-zero alpha. Good news is the alpha blending artifacts vanished, bad news is I have blue lines instead of black, so powers of 2 didn't make any difference. 0 Quote Share this post Link to post
Graf Zahl Posted August 12, 2015 This is a bit odd. On the second layer it was clearly visible that the black artifacts are not at the texture border but right in the middle, at texure coordinate 0.5. 0 Quote Share this post Link to post
Urthar Posted August 12, 2015 That might be just to do with how I constructed the 512x256 (and the 384x192 had a similar offset) 0 Quote Share this post Link to post
Da Werecat Posted August 12, 2015 What's the benefit of making them one texture? 0 Quote Share this post Link to post
Urthar Posted August 12, 2015 Can the Hardware Shader access more than one texture at a time? I don't really know, I just copied Boris's original SILVER4 shader and hacked it to get what I wanted. Speaking of which here's the updated shader I used for the 512x256. uniform float timer; vec4 Process(vec4 color) { // get uv coordinates vec2 uppersky = gl_TexCoord[0].st; vec2 lowersky = gl_TexCoord[0].st; // scroll upper sky uppersky.xy += timer * 0.05; // uppersky is right half of texture uppersky.x = ((uppersky.x - floor(uppersky.x)) * 0.25) + 0.625; uppersky.y = ((uppersky.y - floor(uppersky.y)) * 0.5) + 0.25; // scroll lowersky lowersky.xy += timer * 0.1; // lowersky is left half of texture lowersky.x = ((lowersky.x - floor(lowersky.x)) * 0.25) + 0.125; lowersky.y = ((lowersky.y - floor(lowersky.y)) * 0.5) + 0.25; // get texel for updated uv coordinates vec4 lowerskyTexel = getTexel(lowersky); vec4 upperskyTexel = getTexel(uppersky); // Mix lower and upper sky return color * mix(upperskyTexel, lowerskyTexel, lowerskyTexel.a); } 0 Quote Share this post Link to post
Graf Zahl Posted August 12, 2015 Urthar said:Can the Hardware Shader access more than one texture at a time? No, I have been working on that stuff but it got stalled due to lack of time. 0 Quote Share this post Link to post
boris Posted August 12, 2015 It's a bit weird. I played around a bit, and even if I stay well away from any borders I still get black seams. Not what I was expecting. [edit] I'm using a 384x192 texture, and the seam on the x-axis is every 384 pixels. 0 Quote Share this post Link to post
Graf Zahl Posted August 12, 2015 The only thing in here I can suspect is the (x-floor(x)) stuff. Who knows if it fails for certain values...? 0 Quote Share this post Link to post
Urthar Posted August 12, 2015 I'll try using mod 128, and see how that works out. 0 Quote Share this post Link to post
andrewj Posted August 13, 2015 I think the shader is fine and the problem is how the engine handles geometry. 0 Quote Share this post Link to post
Graf Zahl Posted August 13, 2015 andrewj said:I think the shader is fine and the problem is how the engine handles geometry. How that? A wall is a totally ordinary triangle fan. Absolutely nothing special about it. If this was geometry related the effect should look different. 0 Quote Share this post Link to post
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.