simple lighting with asm shader

Started by
1 comment, last by 21st Century Moose 9 years, 5 months ago

SOLVED solution is written in a reply

hello im trying to make some basic lighting however whenever i rotate my object it get inproper light calculations:

heres a video: whenever i rotate around 90 degs light isnt properly calculated but when i rotate it by 180 degs everything is normal

let me first post the code, after that i will describe what it should do:

THERES ALSO PEUDO CODE OF SHADER AT THE BOTTOM THAT CONTAINS 9 lines and thats exactly what this shader in asm DO

!!ARBvp1.0

#world * view* projection matrix
PARAM MVP1 = program.local[1];
PARAM MVP2 = program.local[2];
PARAM MVP3 = program.local[3];
PARAM MVP4 = program.local[4];
#lightpos
PARAM LPOS = program.local[5];
#light diff
PARAM LDIFF = program.local[6];
#light amb
PARAM LAMB = program.local[7];

#world matrix
PARAM WM1 = program.local[8];
PARAM WM2 = program.local[9];
PARAM WM3 = program.local[10];
PARAM WM4 = program.local[11];

TEMP vertexClip;

#transform vertex for to view clip space (not used in further calculations)
DP4 vertexClip.x, MVP1, vertex.position;
DP4 vertexClip.y, MVP2, vertex.position;
DP4 vertexClip.z, MVP3, vertex.position;
DP4 vertexClip.w, MVP4, vertex.position;

TEMP vertexWorld;

#transform vertex to actual world position this is the most true position of all (used to calculate vector from light to vertex)
DP4 vertexWorld.x, WM1, vertex.position;
DP4 vertexWorld.y, WM2, vertex.position;
DP4 vertexWorld.z, WM3, vertex.position;
DP4 vertexWorld.w, WM4, vertex.position;

TEMP TRANSFORMED_NORMAL;

#transform normal by world matrix
DP3 TRANSFORMED_NORMAL.x, WM1, vertex.normal.x;
DP3 TRANSFORMED_NORMAL.y, WM2, vertex.normal.y;
DP3 TRANSFORMED_NORMAL.z, WM3, vertex.normal.z;

#vector from light to vertex
#helper var

TEMP LIGHT_TO_VERTEX_VECTOR;
TEMP InvSqrLen;

#get direction from Light pos to transformed vertex then normalize it
SUB LIGHT_TO_VERTEX_VECTOR, vertexWorld, LPOS;

#calculate 1.0 / sqrt( LIGHT_TO_VERTEX_VECTOR^2 );
DP3 InvSqrLen.x, LIGHT_TO_VERTEX_VECTOR, LIGHT_TO_VERTEX_VECTOR;
RSQ InvSqrLen.x, InvSqrLen.x;

TEMP LIGHT_TO_VERTEX_NORMAL;

#normalize normal of light-vertex vector
MUL LIGHT_TO_VERTEX_NORMAL.x, LIGHT_TO_VERTEX_VECTOR.x, InvSqrLen.x;
MUL LIGHT_TO_VERTEX_NORMAL.y, LIGHT_TO_VERTEX_VECTOR.y, InvSqrLen.x;
MUL LIGHT_TO_VERTEX_NORMAL.z, LIGHT_TO_VERTEX_VECTOR.z, InvSqrLen.x;

#dot product of normalized vertex normal and light to vertex direction
TEMP DOT;

#dot
DP3 DOT, LIGHT_TO_VERTEX_NORMAL, TRANSFORMED_NORMAL;

#new vertex color
TEMP NEW_VERTEX_COLOR;

#since normals that face each other produce negative dot product we do 0.0 - dotp
SUB NEW_VERTEX_COLOR.x, 0.0, DOT;
SUB NEW_VERTEX_COLOR.y, 0.0, DOT;
SUB NEW_VERTEX_COLOR.z, 0.0, DOT;


#clamp to 0
MAX NEW_VERTEX_COLOR.x, 0.0, NEW_VERTEX_COLOR.x;
MAX NEW_VERTEX_COLOR.y, 0.0, NEW_VERTEX_COLOR.y;
MAX NEW_VERTEX_COLOR.z, 0.0, NEW_VERTEX_COLOR.z;
#clamp to 1
MIN NEW_VERTEX_COLOR.x, 1.0, NEW_VERTEX_COLOR.x;
MIN NEW_VERTEX_COLOR.y, 1.0, NEW_VERTEX_COLOR.y;
MIN NEW_VERTEX_COLOR.z, 1.0, NEW_VERTEX_COLOR.z;

MUL NEW_VERTEX_COLOR, vertex.color, NEW_VERTEX_COLOR;

MOV result.position, vertexClip;
MOV result.color, NEW_VERTEX_COLOR;
MOV result.texcoord[0], vertex.texcoord;
END

----------------------------------------------------------------------------------------

now to describe that code

!!ARBvp1.0

i have 3 inputs used

World * View * Projection Matrix

World Matrix

light position

first of all i transform the vertex by MVP so i will be able to see it on screen (irrevelant stuff becasue its not used in calculations)

DP4 vertexClip.x, MVP1, vertex.position;
DP4 vertexClip.y, MVP2, vertex.position;
DP4 vertexClip.z, MVP3, vertex.position;
DP4 vertexClip.w, MVP4, vertex.position;

then i transform vertex.position by world matrix same for vertex.normal

DP4 vertexWorld.x, WM1, vertex.position;
DP4 vertexWorld.y, WM2, vertex.position;
DP4 vertexWorld.z, WM3, vertex.position;
DP4 vertexWorld.w, WM4, vertex.position;

DP3 TRANSFORMED_NORMAL.x, WM1, vertex.normal.x;
DP3 TRANSFORMED_NORMAL.y, WM2, vertex.normal.y;
DP3 TRANSFORMED_NORMAL.z, WM3, vertex.normal.z;

then i calculate normal from Light position to the vertex position transfromed by wolrd matrix

SUB LIGHT_TO_VERTEX_VECTOR, vertexWorld, LPOS;

DP3 InvSqrLen.x, LIGHT_TO_VERTEX_VECTOR, LIGHT_TO_VERTEX_VECTOR;
RSQ InvSqrLen.x, InvSqrLen.x;

MUL LIGHT_TO_VERTEX_NORMAL.x, LIGHT_TO_VERTEX_VECTOR.x, InvSqrLen.x;
MUL LIGHT_TO_VERTEX_NORMAL.y, LIGHT_TO_VERTEX_VECTOR.y, InvSqrLen.x;
MUL LIGHT_TO_VERTEX_NORMAL.z, LIGHT_TO_VERTEX_VECTOR.z, InvSqrLen.x;

After that i have Transformed vertex normal (by world matrix) and normal from light position to vertex that contains that transformed normal

I dot them, since negative values of dot say that vectors are facing each other and -1 is maximum which i can get i subrtract it from 0 to get light intensity (0 - (-dot(normal,lightvec)) = 0 + dot()

then i clamp whenever values are smaller than 0 to 0, and clamp whenever valuse are bugger than 1 to 1 to have simple 0..1 range

after that i multiple actual vertex.color * this intensity to get final vertex color

then i send back results to pipeline...

DP3 DOT, LIGHT_TO_VERTEX_NORMAL, TRANSFORMED_NORMAL;

SUB NEW_VERTEX_COLOR.x, 0.0, DOT;
SUB NEW_VERTEX_COLOR.y, 0.0, DOT;
SUB NEW_VERTEX_COLOR.z, 0.0, DOT;

MAX NEW_VERTEX_COLOR.x, 0.0, NEW_VERTEX_COLOR.x;
MAX NEW_VERTEX_COLOR.y, 0.0, NEW_VERTEX_COLOR.y;
MAX NEW_VERTEX_COLOR.z, 0.0, NEW_VERTEX_COLOR.z;

MIN NEW_VERTEX_COLOR.x, 1.0, NEW_VERTEX_COLOR.x;
MIN NEW_VERTEX_COLOR.y, 1.0, NEW_VERTEX_COLOR.y;
MIN NEW_VERTEX_COLOR.z, 1.0, NEW_VERTEX_COLOR.z;

MUL NEW_VERTEX_COLOR, vertex.color, NEW_VERTEX_COLOR;

MOV result.position, vertexClip;
MOV result.color, NEW_VERTEX_COLOR;
MOV result.texcoord[0], vertex.texcoord;

since i dont know what order i use i can only tell that its the same order like its used in this translation matrix:

Image18.gif

help!!!








Matrix ModelViewProjectionMAT;
Matrix ModelMatrix;


TEMP vertexClip;

#transform vertex for to view it
result.vertex.position = ModelViewProjectionMAT * vertex.position;

vertexinWorld = ModelMatrix * vertex.position; 

normal_transformed_by_world = ModelMatrix * vertex.normal;

t3dpoint Light_Vertex_normal = Normalize(   vectorAB(LightPosition, vertexinWorld ) );

float intensity = Dot(Light_Vertex_normal , normal_transformed_by_world);

vertex.color = vertex.color * intensity;
Advertisement

SOLVED SOLVED SOLVED SOLVED SOLVED

i wrote:

DP3 TRANSFORMED_NORMAL.x, WM1, vertex.normal.x;
DP3 TRANSFORMED_NORMAL.y, WM2, vertex.normal.y;
DP3 TRANSFORMED_NORMAL.z, WM3, vertex.normal.z;

instead of
DP3 TRANSFORMED_NORMAL.x, WM1, vertex.normal;
DP3 TRANSFORMED_NORMAL.y, WM2, vertex.normal;
DP3 TRANSFORMED_NORMAL.z, WM3, vertex.normal;

also added normalization after transform

Just as a performance tip - instead of transforming your vertex position and normal by the world matrix, and doing so for each vertex, you can transform your light position by the inverse world matrix one-time-only before loading it via glProgramLocalParameter calls, then use the vertex position and normal directly in the rest of your calculations.

That will cut down on a good chunk of per-vertex work in your shader, save some instruction slots and register space (which I'm assuming are important since you're using ASM programs) at the expense of a small bit of one-time-only CPU-side work.

Direct3D has need of instancing, but we do not. We have plenty of glVertexAttrib calls.

This topic is closed to new replies.

Advertisement