About Store Forum Documentation Contact



Post Reply 
Shader image problem
Author Message
Biga Offline
Member

Post: #1
Shader image problem
I would like use an image in shader as a color map.
I have a large image which represents provinces where their IDs stored in image R and G values.

I use a 2nd hardware image to map ID to a color for different mapmodes. (provincesnum X 1 map image, where mapmode color assigned to province ID).
Both images passed to shader via GetShaderImage->set.

I noticed that I can use only created hardware image or texture image pointer from material->base_0. As my image is large, only this 2nd option works, but Im experiencing problems with colors.

For example, on original picture, I have Russia identified with ID 47, which means it has R=0,G=47,B=0 color in colormap. But after Im using it from texture, it varies between 47 and 48, causing dot like shader texturing, not solid one.
Interestingly though that this effect appears only on some areas, see USA is rather solid blue.
How can I get an existing image without color changes to shader?

thanks

   
   
06-10-2014 11:12 AM
Find all posts by this user Quote this message in a reply
Biga Offline
Member

Post: #2
RE: Shader image problem
ok, seems Im advancing with using create2d with correct resolutions (2^x coords)
06-10-2014 01:47 PM
Find all posts by this user Quote this message in a reply
Biga Offline
Member

Post: #3
RE: Shader image problem
hm seems my texture does some antialiasing?

sample test code for creating map image:

PHP Code:
AllianceMapImage.create2D(2561IMAGE_R8G8B8);
   
AllianceMapImage.lock(LOCK_WRITE);
   
Color acolor(000);
   
Color nato(00255);
   
Color wp(25500);
   
REP(256)
   {
      
AllianceMapImage.color(i0acolor); 
   }
   
   
AllianceMapImage.color(10nato);  // Canada
   
AllianceMapImage.color(20nato);  // USA
   
AllianceMapImage.color(360nato); // UK
      
   
AllianceMapImage.color(470wp); // Poland
   
AllianceMapImage.color(480wp); // Russia
   
AllianceMapImage.color(660wp); // Hungary
   
AllianceMapImage.unlock();   
   
   
   
GetShaderImage(8"ProvinceMapImage")->set(ProvinceMapImage);
   
GetShaderImage(8"AllianceImage")->set(AllianceMapImage); 

shader part:

/******************************************************************************/
PHP Code:
// PIXEL SHADER
/******************************************************************************/
Vec4 PS
(
   
Vec2 inTex:TEXCOORD0
):COLOR
{
   
   
Flt id0=Tex(ProvinceMapImage      inTex          ).r  
   
Flt id1=Tex(ProvinceMapImage      inTex          ).g  
   
Flt id = ((id0 256) + id1);
   
Vec2 acoord Vec2(id,1);
   
Vec flow=Tex(AllianceImageacoord).rgb

   return 
Vec4(flow1.0f);


result:

   

notice Slovakia , it isnt set in AllianceMap, Canada is set
but a gradient color sampled for both, though they should be black.
how can I get/access the right color/hit for this texture in shader?
any ideas greatly appreciated



yeah it definitly does a gradient:

   

how can I disable it?
(This post was last modified: 06-10-2014 03:31 PM by Biga.)
06-10-2014 03:13 PM
Find all posts by this user Quote this message in a reply
georgatos7 Offline
Member

Post: #4
RE: Shader image problem
Can't see the images you posted.
Can you fix them?

EDIT : Nvm i see them. I will have a look later and i'll let you know if i find anything.
(This post was last modified: 06-10-2014 05:01 PM by georgatos7.)
06-10-2014 04:48 PM
Find all posts by this user Quote this message in a reply
Biga Offline
Member

Post: #5
RE: Shader image problem
last PNG is the result of exportPNG() of that image.
interestingly .Net Paint shows it normally without gradients, but Irfanview show the gradients shown above... and I assume this version using while sampling... I would need just the 3 unique colors in image, black, blue and red.
06-10-2014 04:56 PM
Find all posts by this user Quote this message in a reply
Biga Offline
Member

Post: #6
RE: Shader image problem
D.texMipFilter(false);
D.texFilter(0);

solves the problem, but unfortunately it is global setting, for all textures.
I would need somehow set in shader only for the proper texture, according to this link:
http://stackoverflow.com/questions/27000...ing-anti-a
but for now I cant find how it is applicable to EE shader...
06-10-2014 07:28 PM
Find all posts by this user Quote this message in a reply
georgatos7 Offline
Member

Post: #7
RE: Shader image problem
Not sure what you're trying to do with the shader and what is the problem. Are you trying to use a shader to edit the texture of the earth model in order to change the color of a country?

//I also don't get this...
Flt id0=Tex(ProvinceMapImage , inTex ).r ;
//Isn't the ProvinceMap a variation of green only? So the r value is always 0?

//And this...
Flt id = ((id0 * 256) + id1);
Vec2 acoord = Vec2(id,1);
//Aren't the id0 and id1 color values? Why are you using them as UV texture coordinates?

Also keep in mind that when you're using the default texture mapping "Vec colorRGB = Tex(image, uvCoord).rgb" then the default sampler uses the GPU's hardware texture filtering to create a gradient color change (linear interpolation) between the samplings.

You can try "Vec colorRGB = image.Sample(SamplerPoint, uvCoord).rgb" instead which uses the nearest neighbour but not sure if this is an issue.
Also make sure you are sampling on the pixel centers and not between them so that they get blended.



EDIT:

-As far as i know the aliasing must be an issue of using the default sampler.
Use the nearest neighbour instead.

-Make sure there isn't a difference between your sampling resolution (inTex) and the actual image resolution.

-Also make sure your uvCoords (sampling coordinates) are exactly at the center of the pixels always.



EDIT 2:

-Oh and maybe set your texture to full instead of compresed (double click it in the editor).
(This post was last modified: 06-10-2014 08:20 PM by georgatos7.)
06-10-2014 08:02 PM
Find all posts by this user Quote this message in a reply
Biga Offline
Member

Post: #8
RE: Shader image problem
I store province (country) ID in R and G (id = (R * 256) + G).
As I have < 255 items, the image has green gradients.
This is used for province ID identification, that works.
In addition I have an another small image where one pixel is for one country.
Color of pixel represent the alliance color.

So theoretically
1. I find the ID which represents the X coord of map image.
2. I access by ID=X coord to the 2nd image for alliance color
3. shader colors that pixel to alliance color.

(and this method, if would work, I can use for any mapmodes just providing the proper map image to shader)

I tried now the sampler state settings, they are ineffective or I just misused them...

PHP Code:
Image ProvinceMapImage;   // province IDs
Image AllianceImage sampler_state {   // Alliance map image
    
MipFilter None;
    
MinFilter None;
    
MagFilter None;
}; 

I try the centers....

(06-10-2014 08:02 PM)georgatos7 Wrote:  EDIT 2:

-Oh and maybe set your texture to full instead of compresed (double click it in the editor).

it is a generated image, not from editor.

PHP Code:
AllianceMapImage.create2D(2561IMAGE_R8G8B8A8);
   
AllianceMapImage.lock(LOCK_WRITE);
   
Color acolor(000);
   
Color nato(00255);
   
Color wp(25500);
   
REP(256)
   {
      
AllianceMapImage.color(i0acolor); 
   }
   
   
AllianceMapImage.color(10nato); 
   
AllianceMapImage.color(20nato); 
   
AllianceMapImage.color(360nato); 
      
   
AllianceMapImage.color(470wp); 
   
AllianceMapImage.color(480wp); 
   
AllianceMapImage.color(660wp);
   
AllianceMapImage.unlock();   
   
   
AllianceMapImage.Export("Data/alliancemap.png");
   
   
GetShaderImage(8"ProvinceMapImage")->set(ProvinceMapImage);
   
GetShaderImage(8"AllianceImage")->set(AllianceMapImage); 
(This post was last modified: 06-10-2014 08:23 PM by Biga.)
06-10-2014 08:18 PM
Find all posts by this user Quote this message in a reply
georgatos7 Offline
Member

Post: #9
RE: Shader image problem
I see. Correct me if i'm wrong but you want to use the shader (as a post process only?) to replace the country's color (green gradient) by the alliance color (Blue, Red, Black).

Maybe you wanna try in the shader something like...

CPP
Renderer(Render);
Shaders("User/myShader").getTech("PostProcessTechnique").draw(null, null);

// PIXEL SHADER
/******************************************************************************/
Vec4 PS
(
Vec2 inTex:TEXCOORD0
):COLOR
{
//Flt id0=Tex(Col, inTex).r ; //Since it's not needed lets forget about red for now.
Flt id1=Tex(Col, inTex).g ;

//The UVTexCoords are 0-1 and the country IDs are the color values of 1-255 in color (0 is not used) then
Flt id = (id1+0.5f)/256.0f; //So for e.x. for Russia id1=47 means the 47th pixel which should be sampled at the 47.5/256 and since the sampling point is in the range of 0-1 xCoord = (47+0.5)/256=47.5/256 = 0.186

Vec2 acoord = Vec2(id,0.5f);
Vec flow=Tex(AllianceImage, acoord).rgb;

return Vec4(flow, 1.0f);
}

I think this will work and i hope i didn't misanderstoud again. So maybe you can try it and i hope im not wrong.

Will be helpful if you tell me how you are accesing the shader in cpp in the esenthel's code editor?

EDIT : I corrected an error that i had.

Replaced
Vec2 acoord = Vec2(id,(0.5/256.0f));

With this
Vec2 acoord = Vec2(id,0.5f);
(This post was last modified: 06-10-2014 09:57 PM by georgatos7.)
06-10-2014 08:49 PM
Find all posts by this user Quote this message in a reply
Biga Offline
Member

Post: #10
RE: Shader image problem
I tried first interpret Tex sampling as UV and used / mapsize formula, but it surprisingly doesnt work, renders all countries blue.
If I use it as ID, it gives back the above result. I dont understand how it is possible...

using the shader in my project:

initpre:

PHP Code:
D.setGetShaderFunc(GetShader); 

init:
..
PHP Code:
earth_with_custom_shader=*TerrainMaterial;
   
earth_with_custom_shader.user_shader=MUS_CUSTOM;
   
earth_with_custom_shader.validate();
...
   
GetShaderImage(8"ProvinceMapImage")->set(ProvinceMapImage);
   
GetShaderImage(8"AllianceImage")->set(AllianceMapImage); 

function:

PHP Code:
ShaderTechGetShader(RENDER_MODE modeMaterial *material[4], UInt mesh_base_flagInt lod_indexBool allow_tesselation)
{
   if(
material[0])switch(material[0]->user_shader)
   {
      case 
MUS_CUSTOM:
      {
         if(
mode==RM_BLEND)return Shaders("User/Custom Shader")->firstTech();
         return 
NULL;
      }break;
   }
   return 
GetDefaultShader(modematerialmesh_base_flaglod_indexallow_tesselation);


thanks for your effort.

(06-10-2014 08:49 PM)georgatos7 Wrote:  I see. Correct me if i'm wrong but you want to use the shader (as a post process only?) to replace the country's color (green gradient) by the alliance color (Blue, Red, Black).

one difference that I have 3 textures

1. terrain texture - displayed on the earth mesh originally
2. province id map - texture for identifying province - used by shader
3. alliance (or other) maps - for mapping ID-color - used by shader

shader gets the underlying province id and colors the pixel by matched alliance color.
(This post was last modified: 06-10-2014 11:34 PM by Biga.)
06-10-2014 11:30 PM
Find all posts by this user Quote this message in a reply
georgatos7 Offline
Member

Post: #11
RE: Shader image problem
Oh i see. Seems like you were not aiming for post process but normal object shader. So give me some time and i'll see what i can do.
06-10-2014 11:38 PM
Find all posts by this user Quote this message in a reply
Biga Offline
Member

Post: #12
RE: Shader image problem
EDIT:

Quote:Flt id1=Tex(Col, inTex).g ;

I use here an image get from EE source, not Col.

GetShaderImage(8"ProvinceMapImage")->set(ProvinceMapImage);

and using that in shader
Image ProvinceMapImage;
...

PHP Code:
Flt id0=Tex(ProvinceMapImage      inTex          ).r  
   
Flt id1=Tex(ProvinceMapImage      inTex          ).g  
   
Flt id = ((id0 256.0f) + id1 0.5f) / 256.0f;
   
Vec2 acoord Vec2(id,0.5f);
   
Vec flow=Tex(AllianceImageacoord).rgb

result:

   

(06-10-2014 11:38 PM)georgatos7 Wrote:  Oh i see. Seems like you were not aiming for post process but normal object shader. So give me some time and i'll see what i can do.

ok, thank you!
(This post was last modified: 06-10-2014 11:53 PM by Biga.)
06-10-2014 11:52 PM
Find all posts by this user Quote this message in a reply
georgatos7 Offline
Member

Post: #13
RE: Shader image problem
Think i found it.
Check this plz...



/******************************************************************************/
#include "Main.h"
/******************************************************************************/
// VERTEX SHADER
/******************************************************************************/
void VS
(
// vertex input
VtxInput vtx,

// output
out Vec2 outTex:TEXCOORD,
out Vec4 outVtx:POSITION
)
{
outTex=vtx.tex(); // copy output texture coordinates

Vec view_space_pos= TransformPos(vtx.pos4()) ; // transform input mesh vertex position by 'object/camera matrix' to view space
Vec view_space_nrm=Normalize(TransformDir(vtx.nrm ())); // transform input mesh vertex normal by 'object/camera matrix' to view space and normalize it

outVtx=Project(view_space_pos); // return output position transformed by projection matrix
}
/******************************************************************************/
// PIXEL SHADER
/******************************************************************************/
Vec4 PS
(
Vec2 inTex:TEXCOORD
):COLOR
{
//Flt id0=Tex(ProvinceMapImage, inTex).r ; //Since it's not needed lets forget about red for now.
Flt id1=Tex(ProvinceMapImage, inTex).g * 255.0f; //<<<<<-------------------------------------- LOL this was possibly the error.

//The UVTexCoords are 0-1 and the country IDs are the color values of 1-255 in color (0 is not used) then
Flt id = (id1+0.5f)/256.0f; //So for e.x. for Russia id1=47 means the 47th pixel which should be sampled at the 47.5/256
and since the sampling point is in the range of 0-1 xCoord = (47+0.5)/256=47.5/256 = 0.186

Vec2 acoord = Vec2(id,0.5f);
Vec flow=Tex(AllianceImage, acoord).rgb;

return Vec4(flow, 1.0f);
}
/******************************************************************************/
// TECHNIQUE
/******************************************************************************/
TECHNIQUE(Main, VS(), PS()); // create the Shader's Main Technique which will be automatically used for meshes, here you can specify custom Vertex/Pixel Shader functions
/******************************************************************************/
(This post was last modified: 06-11-2014 12:38 AM by georgatos7.)
06-11-2014 12:18 AM
Find all posts by this user Quote this message in a reply
Biga Offline
Member

Post: #14
RE: Shader image problem
HAHA
works, thank you very much smile
I owe you sending at least a cold beer smile
06-11-2014 11:15 AM
Find all posts by this user Quote this message in a reply
Post Reply