About Store Forum Documentation Contact



Post Reply 
[Solved]Problem sampling a texture in a shader
Author Message
3DRaddict Offline
Member

Post: #1
[Solved]Problem sampling a texture in a shader
This is driving me nuts...

I have a custom shader with this declaration for a heightmap image:
Image HMap;

In the VS section of the shader I have:
Vec4 shore = TexLod( HMap, Vec4(vtx.tex(),0,0));

In the Application code Init() section I have:
GetShaderImage(8"HMap")->set(UID(807597554, 1102294221, 1108077236, 1492873849));

Problem: I am unable to obtain any values of "shore" within the shader
i.e. shore.x=0 , shore.y=0, shore.z=0 and shore.w=0

'HMap' is not the only texture that I'm trying to sample. The same result is obtained from all the other textures I'm attempting to sample in the PS section of the shader.

The only texture I can sample correctly is my base texture via:
Vec inColor.rgb=Tex(Col, inTex).rgb;
but when I try to do the same for a custom texture 'MyImage':
Vec inColor.rgb=Tex(MyImage, inTex).rgb;
only zeros are obtained.

These custom shaders are crucial to my project, so if I do not obtain decent results soon then I'll have to abandon this project using EE.
(This post was last modified: 09-16-2014 09:41 PM by 3DRaddict.)
09-15-2014 02:09 PM
Visit this user's website Find all posts by this user Quote this message in a reply
Rubeus Offline
Member

Post: #2
RE: Problem sampling a texture in a shader
I may be way off base here, but it may be that you aren't using HMap.Lock before attempting to read/write. Trying to access the pixel/color data without locking first will result in always returning 0, 0, 0.
I use something like:
MyImage.lock( LOCK_READ_WRITE );
Color OldColor = MyImage.color( x, y );
MyImage.color( x, y, NewColor );
MyImage.unlock( );
09-15-2014 07:47 PM
Find all posts by this user Quote this message in a reply
Esenthel Online
Administrator

Post: #3
RE: Problem sampling a texture in a shader
If you're using DX9 not all Image formats can be read from Vertex Shader.
Please look into "Water.cpp" Engine code in the source, lines around:
if(D.validUsage(D3DUSAGE_QUERY_VERTEXTEXTURE, D3DRTYPE_TEXTURE, image->hwType())) // if can use existing format
09-16-2014 02:58 AM
Find all posts by this user Quote this message in a reply
3DRaddict Offline
Member

Post: #4
RE: Problem sampling a texture in a shader
@Esenthel:
I'm actually using DX10+ and, as I mentioned, I also have the same problem when sampling a texture in the Pixel Shader. I did change the properties of my 256x256 .bmp heightmap image from Compressed to Full, but it made no difference.

@Rubeus: Thanks for your suggestion. I do use lock/unlock when accessing images in my normal code. I'm not sure whether that would apply from within a shader... I've never come across it in HLSL. Anyway, I'll investigate.
09-16-2014 05:45 AM
Visit this user's website Find all posts by this user Quote this message in a reply
Esenthel Online
Administrator

Post: #5
RE: Problem sampling a texture in a shader
Please provide a reproduction of the issue and I can investigate that.

I think Rubeus was talking only about accessing colors from CPU side.
09-16-2014 09:19 AM
Find all posts by this user Quote this message in a reply
3DRaddict Offline
Member

Post: #6
RE: Problem sampling a texture in a shader
Whilst preparing a test shader sample for Esenthel, I discovered the source of my problem. Here is the shader test sample code with comments showing where I went wrong. The test is very simple:- it will color the test mesh green if HMap has been sampled correctly, red otherwise.
Code:
/******************************************************************************/
#include "Main.h"
/******************************************************************************/
/******************************************************************************/
// PARAMETERS
/******************************************************************************/
BUFFER(SamplerTest) // store parameters in custom Constant Buffer
//
BUFFER_END

Image HMap;
//texture HMap; // This is not acceptable in EE code,
                // but would be used by a standard HLSL sampler
Image DiffuseMap;

//*****************************************************************************
//TEXTURE SAMPLER
//*****************************************************************************

sampler HMapSampler = sampler_state
{
   Texture = <HMap>;
   MinFilter = LINEAR;
   MagFilter = LINEAR;
   MipFilter = LINEAR;
   AddressU  = WRAP;
   AddressV  = WRAP;
};
sampler DiffuseMapSampler = sampler_state
{
   Texture = <DiffuseMap>;
    MinFilter = LINEAR;
   MagFilter = LINEAR;
   MipFilter = LINEAR;
   AddressU  = WRAP;
   AddressV  = WRAP;
};

/******************************************************************************/
// VERTEX SHADER
/******************************************************************************/
void VS
(
   // vertex input
   VtxInput vtx,

   // output
   out Vec2 outTex:TEXCOORD0,
   out Vec4 outColor:COLOR,
   out Vec4 outVtx:POSITION
)
{
    outColor=Vec4(0,1,0,1); // default GREEN if all ok

    //sample heightmap using standard HMapSampler...
    //Vec4 shore = tex2Dlod( HMapSampler, Vec4(vtx.tex(),0,0)); //---> THIS COMPILES BUT DOES NOT WORK !!

    //sample heightmap using EE shader code...
    Vec4 shore = TexLod( HMap, Vec4(vtx.tex(),0,0)); //---> THIS WORKS !
    
    //test if 'shore' has any data values = 0
    if (( shore.x==0 )&&( shore.y==0 )&&( shore.z==0 )&&( shore.w==0 ))
        outColor=Vec4(1,0,0,1); //RED if condition is true (i.e.'shore' values are all zero!!!)
    

   outTex=vtx.tex();
   outVtx=Project(TransformPos(vtx.pos4()));
}
/******************************************************************************/
// PIXEL SHADER
/******************************************************************************/
Vec4 PS
(
   Vec2 inTex:TEXCOORD0,
   Vec4 inColor:COLOR
):COLOR
{
   //sample diffuse map using EE shader code...
   inColor.rgb*=Tex(DiffuseMap, inTex).rgb; //---> THIS WORKS !

   //sample diffuse map using standard HLSL with DiffuseMapSampler...
   //inColor.rgb*=tex2D(DiffuseMapSampler, inTex).rgb; //---> THIS COMPILES BUT DOES NOT WORK !!
    

   return inColor;
}
/******************************************************************************/
// TECHNIQUE
/******************************************************************************/
TECHNIQUE(Main, VS(), PS());
/******************************************************************************/

So what it all boils down to is: STICK WITH EE SHADER CODE !

I was trying to mix n' match, which I thought was OK because I did NOT receive any shader compiler errors

Thanks, Esenthel, I would not have picked this up if I had not made this test project.
(This post was last modified: 09-16-2014 01:20 PM by 3DRaddict.)
09-16-2014 01:20 PM
Visit this user's website Find all posts by this user Quote this message in a reply
3DRaddict Offline
Member

Post: #7
RE: [Solved]Problem sampling a texture in a shader
On running my original project the same error occurred (blank HMap)
I was now extremely puzzled ??
How could the test project run ok, and not my original project (with the shader corrections now added) ?
Well, comparing the C++ code for each project I finally pinpointed the problem.

I had this:
PHP Code:
GetShaderImage(8"HMap")->set((UID(807597554,1102294221,1108077236,1492873849)); 

instead of this:
PHP Code:
GetShaderImage(8"HMap")->set(*Images(UID(807597554,1102294221,1108077236,1492873849))); 

I apologise for wasting the time of others with this careless bug on my part.blushing
09-16-2014 10:01 PM
Visit this user's website Find all posts by this user Quote this message in a reply
Esenthel Online
Administrator

Post: #8
RE: [Solved]Problem sampling a texture in a shader
Hi,

Thanks for letting us know about the solution.

For performance reasons the ShaderImage is not reference counted, which means that it does not hold the ImagePtr, but just Image*.
Which in your case, when you set the UID, the ImagePtr gets loaded to set the parameter, but then automatically gets released, as there are no references left.
I'll remove the "set(C ImagePtr&)" function for next release, so only "set(Image*)" and "set(Image&)" will remain.

Code:
GetShaderImage(8"HMap")->set(*Images(UID(807597554,1102294221,1108077236,1492873849)));
This is OK, but you may want to keep a global variable "ImagePtr hmap", initialize it once, and set "hmap()" instead. This will be OK as long as you won't release the global 'hmap' variable.
This will be faster because "Images(UID(..))" always needs to look in the Images cache for that image by its ID.
09-17-2014 04:24 AM
Find all posts by this user Quote this message in a reply
Post Reply