Am I doing something with this program?

I use Ogre3D as a graphics engine.

I create a grid manually that works fine, uvs are correct and set to represent the grid coordinates (for this example, the grid is 10 x 10)

I do nothing in the vertex program and have a very simple fragment program. I included both programs plus a material file for explanation.

My problem is that even with filtering equal to none, the colors do not look the same as the original image (this is just a test image used by them because I had problems creating the texture manually in ogre). It turns out that the problem is not in my code in ogre, but rather in what is connected with the material file or with file / vertex programs.

I also included a screenshot on the left and the original image on the right. The fragment shader also draws a simple grid on top of the vertex, so I can make sure that the uv coordinates went right. What they seem like.

enter image description here

Any insight would be greatly appreciated, as I'm really not sure what I'm doing wrong.

Material File:

// CG Vertex shader definition vertex_program PlainTexture_VS cg { // Look in this source file for shader code source GameObjStandard.cg // Use this function for the vertex shader entry_point main_plain_texture_vp // Compile the shader to vs_1_1 format profiles arbvp1 // This block saves us from manually setting parameters in code default_params { // Ogre will put the worldviewproj into our 'worldViewProj' parameter for us. param_named_auto worldViewProj worldviewproj_matrix // Note that 'worldViewProj' is a parameter in the cg code. } } // CG Pixel shader definition fragment_program PlainTexture_PS cg { // Look in this source file for shader code source GameObjStandard.cg // Use this function for the pixel shader entry_point main_plain_texture_fp // Compile to ps_1_1 format profiles arbfp1 } material PlainTexture { // Material has one technique technique { // This technique has one pass pass { // Make this pass use the vertex shader defined above vertex_program_ref PlainTexture_VS { } // Make this pass use the pixel shader defined above fragment_program_ref PlainTexture_PS { } texture_unit 0 { filtering none // This pass will use this 2D texture as its input texture test.png 2d } texture_unit 1 { texture textureatlas.png 2d tex_address_mode clamp filtering none } } } } 

CG file:

 void main_plain_texture_vp( // Vertex Inputs float4 position : POSITION, // Vertex position in model space float2 texCoord0 : TEXCOORD0, // Texture UV set 0 // Outputs out float4 oPosition : POSITION, // Transformed vertex position out float2 uv0 : TEXCOORD0, // UV0 // Model Level Inputs uniform float4x4 worldViewProj) { // Calculate output position oPosition = mul(worldViewProj, position); // Simply copy the input vertex UV to the output uv0 = texCoord0; } void main_plain_texture_fp( // Pixel Inputs float2 uv0 : TEXCOORD0, // UV interpolated for current pixel // Outputs out float4 color : COLOR, // Output color we want to write // Model Level Inputs uniform sampler2D Tex0: TEXUNIT0, uniform sampler2D Tex1: TEXUNIT1) // Texture we're going to use { //get the index position by truncating the uv coordinates float2 flooredIndexes = floor(uv0); if((uv0.x > 0.9 && uv0.x < 1.1) || (uv0.x > 1.9 && uv0.x < 2.1) || (uv0.x > 2.9 && uv0.x < 3.1) || (uv0.x > 3.9 && uv0.x < 4.1) || (uv0.x > 4.9 && uv0.x < 5.1) || (uv0.x > 5.9 && uv0.x < 6.1) || (uv0.x > 6.9 && uv0.x < 7.1) || (uv0.x > 7.9 && uv0.x < 8.1) || (uv0.x > 8.9 && uv0.x < 9.1)) { float4 color1 = {1.0,0,0,0}; color = color1; } else if((uv0.y > 0.9 && uv0.y < 1.1) || (uv0.y > 1.9 && uv0.y < 2.1) || (uv0.y > 2.9 && uv0.y < 3.1) || (uv0.y > 3.9 && uv0.y < 4.1) || (uv0.y > 4.9 && uv0.y < 5.1) || (uv0.y > 5.9 && uv0.y < 6.1) || (uv0.y > 6.9 && uv0.y < 7.1) || (uv0.y > 7.9 && uv0.y < 8.1) || (uv0.y > 8.9 && uv0.y < 9.1)) { float4 color1 = {1.0,0,0,0}; color = color1; } else { //get the colour of the index texture Tex0 at this floored coordinate float4 indexColour = tex2D(Tex0, (1.0/10)*flooredIndexes); color = indexColour; } } 
+6
source share
1 answer

Okay, so some time has passed since I found a solution to my problems, unfortunately, not online, so I hope this helps anyone who has similar problems.

When creating any texture, you should always make texels of size 2^n * 2^m , where m and n are the width and height of the texture. This was my first mistake, although I did not understand it at that time.

I did not notice this because my main texture atlas was based on this principle and had a texture of 1024 x 1024. What I did not take into account was the size of the texture that I created as a texture index. Since my map was 10 x 10, I created a 10 x 10 texture for indexes, I assume that it is somehow stretched (not sure how it works in the backend) is 16 x 16 or 8 x 8, mixing texels together, how did he do it.

The first thing that prompted me was that I scaled my canvas in Photoshop and found that the mixed colors that he created were the same as those that I received at the output of ogre3d.

Anyway, move on.

As soon as I realized this, I was able to create a texture in Ogre and transfer it as follows

 //Create index material Ogre::TexturePtr indexTexture = Ogre::TextureManager::getSingleton().createManual("indexTexture","General",Ogre::TextureType::TEX_TYPE_2D, 16, 16, 0, Ogre::PixelFormat::PF_BYTE_BGRA, Ogre::TU_DEFAULT); Ogre::HardwarePixelBufferSharedPtr pixelBuffer = indexTexture->getBuffer(); pixelBuffer->lock(Ogre::HardwareBuffer::HBL_NORMAL); const Ogre::PixelBox& pixelBox = pixelBuffer->getCurrentLock(); Ogre::uint8* pDest = static_cast<Ogre::uint8*>(pixelBox.data); Ogre::uint8 counter = 0; for (size_t j = 0; j < 16; j++) { for(size_t i = 0; i < 16; i++) { if(i==8 || i==7) { *pDest++ = 3; // B *pDest++ = 0; // G *pDest++ = 0; // R *pDest++ = 0; // A } else { *pDest++ = 1; // B *pDest++ = 0; // G *pDest++ = 0; // R *pDest++ = 0; // A } counter++; } } pixelBuffer->unlock(); 

So now I have a texture that I can use as an index with some values ​​that I added for testing, these values ​​will eventually be filled at runtime by clicking on the fragment.

Now, in order to convey this texture, I had to transfer it to the correct technique and transfer it to my material, this was done as follows:

 Ogre::MaterialPtr material = Ogre::MaterialPtr(Ogre::MaterialManager::getSingleton().getByName("PlainTexture")); float mapSize = 16; float tas = 2; material->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("mapSize",mapSize); material->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("tas",tas); material->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureName("indexTexture"); 

It also skips two values: mapSize is the size of the map itself in tiles (assuming its square), and t is the size of the texture atlas (the number of different squares of the texture across the width of the atlas).

In order for my material to understand that I just went through, I had to slightly modify my material file as follows:

 // CG Pixel shader definition fragment_program PlainTexture_PS cg { source GameObjStandard.cg entry_point main_plain_texture_fp profiles arbfp1 default_params { param_named tas float param_named } } 

And my pass was also redefined.

 pass { // Make this pass use the vertex shader defined above vertex_program_ref PlainTexture_VS { } // Make this pass use the pixel shader defined above fragment_program_ref PlainTexture_PS { } texture_unit 0 { filtering none } texture_unit 1 { texture textureatlas.png 2d tex_address_mode clamp filtering anisotropic } } 

Then I rewrote the cg fragment fragment program to take into account the changes I made.

 void main_plain_texture_fp( float2 uv0 : TEXCOORD0, // UV interpolated for current pixel out float4 color : COLOR, // Output color we want to write uniform float tas, uniform float mapSize, // Model Level Inputs uniform sampler2D Tex0: TEXUNIT0, uniform sampler2D Tex1: TEXUNIT1) { //get the index position by truncating the uv coordinates float2 flooredIndexes = floor(uv0); //get the colour of the index texture Tex0 at this floored coordinate float4 indexColour = tex2D(Tex0, ((1.0/mapSize) * flooredIndexes)+(0.5/mapSize)); //calculate the uv offset required for texture atlas range = 0 - 255 float indexValue = (255 * indexColour.b) + (255 * indexColour.g) + (255 * indexColour.r); //float indexValue = (tas * tas) - indexValue0; if(indexValue < tas*tas) { float row = floor(indexValue/tas); float col = frac(indexValue/tas) * tas; float uvFraction = 1.0/tas; float uBase = col * uvFraction; float vBase = 1 - ((tas - row) * uvFraction); float uOffset = frac(uv0.x)/tas; float vOffset = (frac(uv0.y))/tas; float uNew = uBase + uOffset; float vNew = vBase + vOffset; float2 uvNew = {uNew, vNew}; if(frac(uv0.x) > 0.99 || frac(uv0.x) < 0.01) { float4 color1 = {1,1,1,0}; color = (0.2*color1) + (0.8*tex2D(Tex1,uvNew)); } else if(frac(uv0.y) > 0.99 || frac(uv0.y) < 0.01) { float4 color1 = {1,1,1,0}; color = (0.2*color1) + (0.8*tex2D(Tex1,uvNew)); } else { color = tex2D(Tex1,uvNew); } } else { float4 color2 = {0.0,0,0,0}; color = color2; } } 

This calculates the correct texel needed from the texture satin, it also overlaps the weak grid on top, combining 80% texel color and 20% white.

If the texture atlas does not have a color index indicated by the index texture, then it simply displays black (this is basically the case that it is very easy to notice.

The following is an example output using a 2 x 2 texture atlas.

enter image description here

+6
source

Source: https://habr.com/ru/post/919428/


All Articles