haqu / tiny-wings

Remake of the popular iPhone game.
MIT License
816 stars 178 forks source link

Procedural Terrain Texture Alpha Issue #10

Closed EnlightenedOne closed 11 years ago

EnlightenedOne commented 12 years ago

I have been reviewing this code for procedural texture generation and seeing how the ground mechanism can be revised. I zoomed out to 0.75 scale and I want to know why the very last triangle appears to be drawn faded as if the highlight method of the render texture does not apply to it. I simply cannot diagnose the root cause and it is driving me absolutely crazy!

It is most noticeable on the very first vertex drawn on the left of the scene and changes over time so presumably is an issue in the resetHillVertices method.

I can only disable the impact of these two triangles by calling glBlend(GL_ONE, GL_ZERO) which makes the hill look really dull.

Setting the vertices used to draw the RenderHighlight to a size significantly larger on the x axis than the texture has no impact on the size of the translucent looking bit.

I have played around with the texture coordinates for the generated vertices with no success as yet can anyone explain this behaviour? I would really like to understand the cause better. I analysed this for a while and it is both the first and last triangles drawn that suffer from this issue.

EnlightenedOne commented 12 years ago

I manually verified the initial texture coordinates are valid below, the texture is clearly drawn correctly for all intensive purposes. See the verifying code below:

int hSegments2 = floorf((hillKeyPoints[1].x-hillKeyPoints[0].x)/(kHillSegmentWidth * CC_CONTENT_SCALE_FACTOR()));
float dx2 = (hillKeyPoints[1].x - hillKeyPoints[0].x) / hSegments2;

hillTexCoords[0] = (ccVertex2F){hillKeyPoints[0].x/(float)textureSize, 0};
hillTexCoords[1] = (ccVertex2F){(hillKeyPoints[0].x + dx2)/(float)textureSize, 0};

hillTexCoords[2] = (ccVertex2F){hillKeyPoints[0].x/(float)textureSize, 1};
hillTexCoords[3] = (ccVertex2F){(hillKeyPoints[0].x + dx2)/(float)textureSize, 1};

Drawing artifiact checks: The texture must be fine because it is repeated over the surface. The texture positions must be fine or there would be invalid drawing artifiact. The coordinates are fine as I just verified. The glColor value ensures the initial value is valid. The drawing process might have issues... The shader might be buggy...

This is what my drawing process looks like: glBindTexture(GL_TEXTURE_2D, _stripes.texture.name);

glDisableClientState(GL_COLOR_ARRAY);

glColor4f(1, 1, 1, 1);

//Disable all alpha ops that might be induced by anything. //glBlendFunc(GL_ONE, GL_ZERO);

glVertexPointer(2, GL_FLOAT, 0, hillVerticies]); glTexCoordPointer(2, GL_FLOAT, 0, hillTexCoords]);

glDrawArrays(GL_TRIANGLE_STRIP, 0, (GLsizei)nHillVertices]);

glEnableClientState(GL_COLOR_ARRAY);

To help you see the issue I have uploaded a photo of it with an empty background and one with a sky. Photobucket

EnlightenedOne commented 12 years ago

If you remove the line "glDisableClientState(GL_COLOR_ARRAY);" in the draw method you can clearly see the area firing off the error, where is the shader being used to draw this? Can anyone see why there is color data bleeding through to the final image?

haqu commented 12 years ago

I don't see this issue, but I looked through the code and found one unbalanced glDisableClientState(GL_COLOR_ARRAY); in renderTopBorder. Try adding glEnableClientState(GL_COLOR_ARRAY); to the end of method.

EnlightenedOne commented 12 years ago

I am using iPhone 5.1 emulator with the iOS 6 SDK and a deployment target of 5.1. Balancing the client states did not help, if I remove the renderHighlight method the issue goes. I modified the code for GLES 2.0 and I still have the issue. One simple solution I wish I had thought of sooner was just to make the render texture have no alpha channel "kCCTexture2DPixelFormat_RGB565" does the trick and doesn't stop you drawing alpha blended colours into the texture over a base colour.

haqu commented 12 years ago

Changing render texture pixel format breaks renderHighlight step, as you can see on comparison screenshot:

pixel format comparison

EnlightenedOne commented 12 years ago

While I can confirm you are 100% correct in GLES 1.0 in GLES 2.0 with the use of Cocos2D's inbuilt shaders this is simply not the case even with the backbuffer using kEAGLColorFormatRGB565 and the texture using kCCTexture2DPixelFormat_RGB565 the shaders still draw the result of the alpha blend operation onto the surface and there is no alpha penalty when using the final texture. The bug in this issue applies accross both versions but not if you disable alpha on the final texture in 2.0! :)

I ported the terrain code to a larger project with GLES 2.0 in it, I am more than happy to share the code surrounding producing the terrain in Cocos 2.0 but I have realised verifying this issue that my rendered texture no longer repeats smoothly. When I have this fixed I will provide the altered source required to port to 2.0. I am suffering a problem drawing the info stats at the same time as using this rendered texture so I was hoping to share the code when I had that solved. The only major kink I had to alter significantly to make things work in 2.0 was the renderBorder being drawn incorrectly.

haqu commented 12 years ago

Interesting. I hope someone working with iOS 6 will confirm this issue and maybe propose the solution.

ZuzooVn commented 11 years ago

Is there any update there?

haqu commented 11 years ago

check out the latest update.

ZuzooVn commented 11 years ago

Do you have any plan to update more feature for this game?

haqu commented 11 years ago

not at this time