🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

How do I edit a texture that is already on a model in OpenGL?

Started by
21 comments, last by hplus0603 1 year, 11 months ago

Ok so I figured out the last issue where the terrain chunk was too big… However, I am still running into another issue. I have the square on the terrain that has a different texture. However, when it moves, it does not leave the texture behind. Instead, it is pretty much just a texture moving across another texture. It is not forcing the terrain to change:

As shown, it is just a small square on the terrain, and the texture is not updated whatsoever.

Advertisement

yaboiryan said:

I have the square on the terrain that has a different texture. However, when it moves, it does not leave the texture behind. Instead, it is pretty much just a texture moving across another texture. It is not forcing the terrain to change:

Where are you changing your texture data? If the texture is not changing, it is pretty clear that your strategy is not working. But more specifics need to be known to give good advice.

@Warp9 Hmmmmm I am not sure of how to change the texture data from stuff in the shader… That is my problem here hahaha! I am not quite sure about how to get the new texture data and “paste” it, if you will, over the old.

@yaboiryan : I would suggest this tutorial right here. . .

@Warp9 So how would I save this texture, then?

My goal is to get the total texture that is being rendered onto the terrain… The issue, which I am finding out now, is that there is no way to get the fragment data from the shader and reconvert it back into a texture… Or, at least, no way that I can think of…

@fleabay @warp9

I tried the following for drawing each part of the terrain:

uniform float colorValues[256] = 
{
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,1,1,1,1,1,1,0,1,1,1,1,1,0,1,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
};

It worked, but it runs slowly due to this:

for(int i = 0; i < (pass_textureCoords.x * 16); i++)
	{
	for(int j = 0; j < (pass_textureCoords.y * 16); j++)
	{
		if(colorValues[i + j*16] == 0)
		{
		blendMapColor.r = 0;
		blendMapColor.g = 0;
		blendMapColor.b = 0;
		}
		if(colorValues[i + j*16] == 1)
		{
		blendMapColor.r = 0;
		blendMapColor.g = 1;
		blendMapColor.b = 0;
		}
		if(colorValues[i + j*16] == 2)
		{
		blendMapColor.r = 0;
		blendMapColor.g = 0;
		blendMapColor.b = 1;
		}
	}

}

Because of these for loops, the game has quite a few issues running at a playable speed.

Open MSPaint, Gimp, Photoshop. Draw some blue lines in it, some green lines in it, some red lines in it. You upload 3 textures for use in your shader: grass, mountain, snow. Also bind the splat map (red,blue,green) from photoshop.

Terrain pixel color = red * texture2D(grass, uvTexture.xy) + blue*texture2D(snow, uvTexture.xy) ……….

Your terrain needs texture coordinates from 0,0 to 1,1 across it. You can multiply to scale how many times the grass repeats by uvTexture = uvValue*scale.

Painting with the mouse the is the next complicated step, you have to either perform a 3D raycast, or use a physics engine that can determine raycasting for you to find the location of the mouse on the terrain. You bind the splat map texture in openGL and you can draw triangles/quads whatever color you want onto it and rebind. There is no history of mouse locations, just simply update the splat texture repeatedly as you paint. If your mouse hits the middle point of terrain, that would be (.5,.5). You load a viewport from glOrtho(0,0, 1,1). and draw a square or whatever you wish at glVertex3f(.5,.5,1). Thats it.



NBA2K, Madden, Maneater, Killing Floor, Sims http://www.pawlowskipinball.com/pinballeternal

So what you really need to do is the texture, you want to be using as a mask to select to display a mix between two textures, bind that as a render target (this is DX speach for a Frame Buffer Object in GL I believe) and render the modification you want to see into that on the position you get from the intersection you calculated before. Then in a second pass you use this texture as the blend mask and it is no longer bound as a render target but as a normal texture.

This means that you have 2 draw passes in your code one to update the mask texture and the other one to actually render the terrain.

Shadow passes and GBuffers for deffered rendering work in very similar way to this so this is pretty standard in normal rendering. I believe the video Warp9 posted is trying to explain this too you.
This might help explain what you are doing: http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-14-render-to-texture/

Worked on titles: CMR:DiRT2, DiRT 3, DiRT: Showdown, GRID 2, theHunter, theHunter: Primal, Mad Max, Watch Dogs: Legion

yaboiryan said:

@Warp9 So how would I save this texture, then?

My goal is to get the total texture that is being rendered onto the terrain… The issue, which I am finding out now, is that there is no way to get the fragment data from the shader and reconvert it back into a texture… Or, at least, no way that I can think of…

If your goal is to get the total texture that is being rendered onto the terrain, you should render that total texture to an alternate buffer, rather than drawing it straight to the screen. You'll then have that total-texture stored in your alternate buffer. Then you can use the data, which is in that buffer, to draw onto the terrain.

As far as saving the image for longer use, you probably want to transfer the data back to the CPU (as opposed to keeping it on the GPU).

Looking at some specific code. . .

yaboiryan said:

It worked, but it runs slowly due to this:

for(int i = 0; i < (pass_textureCoords.x * 16); i++)
{
	for(int j = 0; j < (pass_textureCoords.y * 16); j++)
	{
		if(colorValues[i + j*16] == 0)
		{
		blendMapColor.r = 0;
		blendMapColor.g = 0;
		blendMapColor.b = 0;
		}
		if(colorValues[i + j*16] == 1)
		{
		blendMapColor.r = 0;
		blendMapColor.g = 1;
		blendMapColor.b = 0;
		}
		if(colorValues[i + j*16] == 2)
		{
		blendMapColor.r = 0;
		blendMapColor.g = 0;
		blendMapColor.b = 1;
		}
	}

}

Because of these for loops, the game has quite a few issues running at a playable speed.

So, depending on the values of pass_textureCoords.x and pass_textureCoords.y, it looks like this loop code will run up to 256 times (assuming a textureCoord range of 0.0 to 1.0). However, blendMapColor seems to be the same over the entire loop (unlike your colorValues array, blendMapColor is not an array of colors). So, after all your loop iterations, it looks like only the same 3 variables actually change : blendMapColor.r blendMapColor.g and blendMapColor.b

It just looks like you are resetting those same 3 variables, over and over again, as you run through your loop. Is that what you really want to do?

Assuming that this is code in a fragment shader, it is likely that blendMapColor will change each time the fragment shader is called. But you don't need to run through the whole array of color values for each fragment. You'd probably want to get rid of the loop structure, and find out the relevant colorValue index for that specific fragment. And then set the blendMapColor.r blendMapColor.g and blendMapColor.b values based on that.

This topic is closed to new replies.

Advertisement