🔒 Locked
CG
Advertisement
Original Post
Dear All, I'm currently going through some CG tutorials and have hit some confusion. Specifically, it relates to texturing. I wish to texture an object and use a shader. In the examples given, the image is listed as a series of RGB values in a header file. Is this the only way to use textures with a shader? If so, how does one go about converting an image into a series of rgb values? If not, what other ways are there of passing texture information into a CG shader? Lastly, if someone can point me in the right direction for this. The shader i have is a basic lighting shader. Despite rotating my model around the x axis, because the shader works in object space, the rotation doesnt end up being rendered to the screen. I want to perform the calculations in eye space. Can anyone give me pointers on how to acheive this? I believe its something to do with multiplying the modelview matrix by the inverse transpose of the modelview matrix, but could of course be horribly wrong. Thanks guys for all your help. Steve
Hi,
Just to clarify.
I have a .cg file containing code that obviously is compiled at runtime and performs calculations for basic lighting (Phong).
i.e. the Ka Ia + sigma(Kd (N.L)I + Ks(H.N)^mIs) that I've learned at uni.
It runs as a vertex program.
The program works successfully. My model lights correctly.
I apologise if I'm using incorrect terminology there by using the word shader. So I'll refer to it from here on in as my Vertex Program.
Depends how you define new by the way. New to programming no, new to graphics - not so much after a 3D graphics module - just some problems here and there- I've implemented Progressive Refinement Radiosity for a coursework by myself - so you tell me - does that make me new? ;) I'm a human being and I sometimes can't see the simplest most stupid things.
New to CG? Most definately yes.
I'm reading Shadertech code samples and the CG Tutorial book (but that doesn't have details on how to provide the information required to the .cg program). So I'm having to pick things up as I go along - thats the way I learn best.
As for loading the images - thats fine. What I mean exactly is that I have several models rendered to screen which have BMP textures applied to them. Now, when I write my Fragment Program (which I'm doing now) I obviously want the lighting to be applied to the textured model. To do this don't I need to pass the texture to the Fragment Program? If not, please clarify for me how I achieve this.
You misunderstand me in my question about the header file. In one of the few examples that I could find (Nvidia code sample) where a triangle is textured in a Fragment Shader with a picture of a demon, there was no image file in the entire project. Instead there was a .h file that contained the RGB values in one massive long list and this was read from the header file and passed to the Fragment Program.
Now, what I'm asking is, is this the only way to pass this information (i.e. by creating a huge text file containing the RGB values which represent the image) ?
I hope I've clarified your request for information and hope you can help me further.
Thanks a lot
Just to clarify.
I have a .cg file containing code that obviously is compiled at runtime and performs calculations for basic lighting (Phong).
i.e. the Ka Ia + sigma(Kd (N.L)I + Ks(H.N)^mIs) that I've learned at uni.
It runs as a vertex program.
The program works successfully. My model lights correctly.
I apologise if I'm using incorrect terminology there by using the word shader. So I'll refer to it from here on in as my Vertex Program.
Depends how you define new by the way. New to programming no, new to graphics - not so much after a 3D graphics module - just some problems here and there- I've implemented Progressive Refinement Radiosity for a coursework by myself - so you tell me - does that make me new? ;) I'm a human being and I sometimes can't see the simplest most stupid things.
New to CG? Most definately yes.
I'm reading Shadertech code samples and the CG Tutorial book (but that doesn't have details on how to provide the information required to the .cg program). So I'm having to pick things up as I go along - thats the way I learn best.
As for loading the images - thats fine. What I mean exactly is that I have several models rendered to screen which have BMP textures applied to them. Now, when I write my Fragment Program (which I'm doing now) I obviously want the lighting to be applied to the textured model. To do this don't I need to pass the texture to the Fragment Program? If not, please clarify for me how I achieve this.
You misunderstand me in my question about the header file. In one of the few examples that I could find (Nvidia code sample) where a triangle is textured in a Fragment Shader with a picture of a demon, there was no image file in the entire project. Instead there was a .h file that contained the RGB values in one massive long list and this was read from the header file and passed to the Fragment Program.
Now, what I'm asking is, is this the only way to pass this information (i.e. by creating a huge text file containing the RGB values which represent the image) ?
I hope I've clarified your request for information and hope you can help me further.
Thanks a lot
It isn't the only way.
They probably defined this statically in the header file so they didn't have to put image loading code into the sample project.
When you load an image file it's generally converting the specific file format into a set of RGB values. If you're already using your BMP files as textures, they're in a format that the API can understand.
They probably defined this statically in the header file so they didn't have to put image loading code into the sample project.
When you load an image file it's generally converting the specific file format into a set of RGB values. If you're already using your BMP files as textures, they're in a format that the API can understand.
Texture data usually comes from image files you load, from previously rendered passes, or from data generated in your application if you're using the GPU for general-purpose calculations. If you want to pass textures down to a shader, you need to set up a uniform parameter for that texture in the shader, bind the texture to the parameter in your code with cgGLSetTextureParameter, and enable it using cgGLEnableTextureParameter. Loading textures from files is pretty standard and you can probably find a few free libraries online that do it for you. NeHe's site has a lot of information on working with textures, since a lot of it has nothing to do wth Cg until the final stages where you bind parameters. Using previously rendered passes as textures is more complicated, but I think NeHe has a few tutorials on that as well (probably using FBO's).
Regarding your second question, the vertex shader should at the very least be performing the standrad modelview/projection transformation on the input position and outputting that to the POSITION bind. However, you can perform lighting calculations in either world-space or view-space in the fragment shader, so if you transform the input position by just the modelview matrix but pass that on as well in a TEXCOORD bind, you will have access to the view-space position of the pixel in the fragment shader. Pass the view-space position of the light as a uniform parameter and you can do all the lighting calculations. Something simple might be:
Regarding your second question, the vertex shader should at the very least be performing the standrad modelview/projection transformation on the input position and outputting that to the POSITION bind. However, you can perform lighting calculations in either world-space or view-space in the fragment shader, so if you transform the input position by just the modelview matrix but pass that on as well in a TEXCOORD bind, you will have access to the view-space position of the pixel in the fragment shader. Pass the view-space position of the light as a uniform parameter and you can do all the lighting calculations. Something simple might be:
// Vertex shadervoid main(float4 iPosition : POSITION, float3 iNormal : NORMAL, uniform float4x4 ModelView, uniform float4x4 Projection, out float4 oPosition : POSITION, out float4 oViewPos : TEXCOORD0 out float3 oNormal : TEXCOORD1){ oViewPos = mul(ModelView, iPosition); // Keep view-space position oPosition = mul(Projection, oViewPos); // Apply projection for rendering oNormal = iNormal;} // Fragment shadervoid main(float4 iPosition : POSITION, float4 iViewPos : TEXCOORD0, float3 iNormal : TEXCOORD1, uniform float3 lightPos, out float4 oColor : COLOR){ float3 viewPos = iViewPos.xyz / iViewPos.w; // Perform lighting calculations with viewPos and lightPos oColor = emissive + ambient + diffuse + specular;}
Zipster,
Thanks for a great reply.
I've tried adding your code to mine yet I'm now not getting anything rendered on the screen at all. If you get a chance to look at this and comment would be much appreciated. (P.S - I was getting an output before - it was my objects in object space - now I'm getting nothing).
Thanks
Thanks for a great reply.
I've tried adding your code to mine yet I'm now not getting anything rendered on the screen at all. If you get a chance to look at this and comment would be much appreciated. (P.S - I was getting an output before - it was my objects in object space - now I'm getting nothing).
Thanks
//vertexvoid main(float4 position : POSITION, float3 normal : NORMAL, out float4 oPosition : POSITION, out float4 oViewPos : TEXCOORD0, out float3 oNormal : TEXCOORD1, uniform float4x4 modelViewProj, uniform float4x4 projection){ oViewPos = mul(modelViewProj, position); oPosition = mul(projection, oViewPos); oNormal = normal;}void main(float4 iPosition : POSITION, float4 iViewPos : TEXCOORD0, float3 normal : TEXCOORD1, out float4 color : COLOR, uniform float3 globalAmbient, uniform float3 lightColor, uniform float3 lightPosition, uniform float3 eyePosition, uniform float3 Ke, uniform float3 Ka, uniform float3 Kd, uniform float3 Ks, uniform float shininess){ float3 viewPos = iViewPos.xyz / iViewPos.w; float3 P = viewPos.xyz; float3 N = normalize(normal); float3 emissive = Ke; float3 ambient = Ka * globalAmbient; float3 L = normalize(lightPosition - P); float diffuseLight = max(dot(N,L), 0); float3 diffuse = Kd * lightColor * diffuseLight; float3 V = normalize(eyePosition - P); float3 H = normalize(L + V); float specularLight = pow(max(dot(N,H), 0), shininess); if (diffuseLight <=0) specularLight = 0; float3 specular = Ks * lightColor * specularLight; color.xyz = emissive + ambient + diffuse + specular; color.w = 1;}
You're multiplying by the projection matrix twice, since the first time you multiply by modelViewProj, and then you multiply that result by projection. If you just bind the modelview matrix (CG_GL_MODELVIEW_MATRIX instead of CG_GL_MODELVIEW_PROJECTION_MATRIX) for that parameter, you should see something. I should also mention that you can pass position straight through to the fragment shader completely untouched if you want and it will be in world-space, if that's where you prefer to do your calculations. I'm new to Cg myself but I have a fair amount of experience in HLSL (which is almost the same thing), and the convention there is to do things in view-space, but it's all up to you.
Zipster,
Your help is great. Thanks so much.
One last question. I have an object in my scene which i move around with key presses.
Now, when I update the co-ords of that object and then redraw, why is it that when i'm using my shader, the object doesnt actually move in the scene? It works if I use normal GL lighting. Is it because the rendering is done in Object space?
I'm a little rusty on my GL matrices. Better study them again.
Is there a way I can get around this problem?
Your help is great. Thanks so much.
One last question. I have an object in my scene which i move around with key presses.
Now, when I update the co-ords of that object and then redraw, why is it that when i'm using my shader, the object doesnt actually move in the scene? It works if I use normal GL lighting. Is it because the rendering is done in Object space?
I'm a little rusty on my GL matrices. Better study them again.
Is there a way I can get around this problem?
You're probably just forgetting to update the matrix parameters with cgGLSetStateMatrixParameter. When using the fixed-function pipeline you can just call glRotate, glTranslate, etc., and the transformation state will be updated and applied. But with Cg, since the transformation matrices are explicit uniform parameters you have to set them each time they change. I've been guilty on occasion of forgetting to update the transformations as well.
Hi Zipster,
Its strange because my call to cgGLSetStateMatrixParameter is actually in my render method, so each time the frame is updated that method is being called but still nothing changes????
Its strange because my call to cgGLSetStateMatrixParameter is actually in my render method, so each time the frame is updated that method is being called but still nothing changes????
Make sure your "cgGLSetStateMatrixParameter" call that updates the matrix, comes after all the glRotate/glTranslate/glScale or matrix multiplies that are used for that object. Otherwise, the object will be rendered at its origin (0,0,0) for example, without scaling and rotations. Also make sure that this call is done before all those commands are unapplied, with glPopMatrix for example.
greetings,
Rick
greetings,
Rick
Topic Locked
This topic has been locked by a moderator. New replies are not allowed.
Sign in to reply to this topic.
Advertisement