[英]Opengl-glsl single virtual light
我的着色器有一個小問題。
頂點
varying vec3 normal, lightDir, eyeVec, spotDir;
varying mat4 viewMat;
uniform vec4 posluce; \\this is light position
uniform mat4 matrix;
uniform vec3 spotdir;
void main(){
viewMat = inverse(matrix);
vec3 posLuceWorld = (posluce*viewMat).xyz;
spotDir = normalize(vec3(vec4(spotdir,0)*viewMat));
normal = gl_NormalMatrix * gl_Normal;
vec3 vVertex = vec3(gl_ModelViewMatrix * gl_Vertex);
lightDir = normalize(posLuceWorld.xyz - (gl_Vertex * viewMat).xyz);
eyeVec = normalize(-vVertex);
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
分段
varying vec3 normal, lightDir, eyeVec,spotDir;
varying mat4 viewMat;
const float cos_outer_cone_angle = 0.8; // 36 degrees
void main (void){
vec4 amb = vec4(0.1, 0.1, 0.1, 1.0);
vec4 diff = vec4(0.52, 0.81, 0.98, 1.0);
vec4 spec = vec4(0.52, 0.81, 0.98, 1.0);
float exp = 2.5f;
float cutoff = 25.0f;
float cosCut = cos(cutoff);
vec4 final_color =
(gl_FrontLightModelProduct.sceneColor * gl_FrontMaterial.ambient) +
(amb * gl_FrontMaterial.ambient);
vec3 L = lightDir;
vec3 D = spotDir;
float cos_cur_angle = dot(-L, D);
float cos_inner_cone_angle = cosCut;
float cos_inner_minus_outer_angle =
cos_inner_cone_angle - cos_outer_cone_angle;
float spot = 0.0;
spot = clamp((cos_cur_angle - cos_outer_cone_angle) /
cos_inner_minus_outer_angle, 0.0, 1.0);
vec3 N = normalize(normal);
float lambertTerm = max( dot(N,L), 0.0);
if(lambertTerm > 0.0){
final_color += diff *
exp *
gl_FrontMaterial.diffuse *
lambertTerm * spot;
vec3 E = eyeVec;
vec3 R = reflect(-L, N);
float specular = pow( max(dot(R, E), 0.0),
gl_FrontMaterial.shininess );
final_color += spec *
gl_FrontMaterial.specular *
specular * spot;
}
gl_FragColor = final_color;
}
我的顯示功能:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
//Setting camera using orthonormal frame manipulation
Matrix4x4 m;
//Change view with mouse
buildRotationMatrix(camera.frame.Yaxis, deg2rad(-yrot), m);
transform(m, camera.frame.Xaxis);
transform(m, camera.frame.Yaxis);
transform(m, camera.frame.Zaxis);
//i traslate myself with the Keyborad
if (up_key){
camera.position.x += -camera.frame.Zaxis.x * speed;
camera.position.y += -camera.frame.Zaxis.y * speed;
camera.position.z += -camera.frame.Zaxis.z * speed;
}
if (down_key){
camera.position.x += camera.frame.Zaxis.x * speed;
camera.position.y += camera.frame.Zaxis.y * speed;
camera.position.z += camera.frame.Zaxis.z * speed;
}
if (left_key){
camera.position.x += -camera.frame.Xaxis.x * speed;
camera.position.y += -camera.frame.Xaxis.y * speed;
camera.position.z += -camera.frame.Xaxis.z * speed;
}
if (right_key){
camera.position.x += camera.frame.Xaxis.x * speed;
camera.position.y += camera.frame.Xaxis.y * speed;
camera.position.z += camera.frame.Xaxis.z * speed;
}
pitch-=xrot*0.5; // change view speed
if (pitch>90) pitch=90;
if (pitch<-90) pitch=-90;
Camera temp(camera);
Matrix4x4 m2;
buildRotationMatrix(temp.frame.Xaxis, deg2rad(pitch), m2);
transform(m2, temp.frame.Xaxis);
transform(m2, temp.frame.Yaxis);
transform(m2, temp.frame.Zaxis);
Matrix4x4 c;
buildCameraMatrix(temp,c);
glMultMatrixf(c.GL_array());
if(mouse_moved){
mouse_moved=false;// this force my mouse in center
glutWarpPointer(width/2, height/2);
}
xrot=yrot=0;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
GLdouble ratio = static_cast<GLdouble>(width) / static_cast<GLdouble>(height);
gluPerspective(45, //angolo di visuale
ratio, //aspect ratio (rapporto tra larghezza e altezza)
1, //Z near cutting plane
1000); //Z far cutting plane
glMatrixMode(GL_MODELVIEW);
glUseProgram(ShaderProgram);
GLint matrixR = glGetUniformLocation(ShaderProgram, "matrix");
glUniformMatrix4fv(matrixR, 1, GL_FALSE, c.GL_array());
GLint spot = glGetUniformLocation(ShaderProgram, "spotdir");
float spotdirr[3] = {0.0, -1.0, 1.0};
glUniform3fv(spot,1,spotdirr);
GLint pos = glGetUniformLocation(ShaderProgram, "posluce");
float light0_position[4] = {-0.17252*scale, 0.73089*scale, -0.52868*scale, 1};
glUniform4fv(pos,1,light0_position);
glPushMatrix();
creaPavimento(); \\this create my floor
glPopMatrix();
glPushMatrix();
GLfloat front_mat_diffuse[] = {0.25, 0.4, 0.98, 1.0};
GLfloat front_mat_spec[] = {0.4, 0.4, 0.4, 1.0};
GLfloat front_mat_ambi[] = {0.25, 0.25, 0.25, 1.0};
glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, front_mat_diffuse);
glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, front_mat_spec);
glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT, front_mat_ambi);
GLfloat mShininess[] = {2};
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mShininess);
glTranslatef(0.0,1.0,6.0);
glutSolidSphere(0.5, 20, 20);
glPopMatrix();
glFlush();
glutSwapBuffers();
當我使用此着色器時,產生的光線不會照亮我的地板,而只會照亮一個球體,這是我的問題:為什么? 怎么了? 如果我使用OPENGL標准燈,效果很好。
我無法發布圖片。 對不起,我英語不好。
編輯:
我已經更改了一點着色器。 現在對地板和球體都適用,但是對於球體來說,地板截斷是完全錯誤的,但是方向卻是錯誤的。
頂點:
varying vec3 normal, lightDir, eyeVec, spotDirection;
varying mat4 viewMat;
uniform vec4 posluce;
uniform mat4 matrix;
uniform vec3 spotdir;
void main(){
viewMat = inverse(matrix);
spotDirection = normalize(vec3(vec4(spotdir,0.0)*viewMat));
vec3 lightPosition = (posluce * viewMat).xyz;
normal = gl_NormalMatrix * gl_Normal;
vec3 vVertex = vec3(gl_ModelViewMatrix * gl_Vertex);
lightDir = normalize( (gl_Vertex * viewMat).xyz + lightPosition);
eyeVec = -vVertex;
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
這是新片段:
varying vec3 normal, lightDir, eyeVec,spotDirection;
varying mat4 viewMat;
const float cos_outer_cone_angle = 0.8; // 36 degrees
void main (void){
vec4 amb = vec4(0.1, 0.1, 0.1, 1.0);
vec4 diff = vec4(0.52, 0.81, 0.98, 1.0);
vec4 spec = vec4(0.52, 0.81, 0.98, 1.0);
float exp = 2.5f;
float cutoff = 25.0f;
float cosCut = cos(cutoff);
vec4 final_color =
(gl_FrontLightModelProduct.sceneColor * gl_FrontMaterial.ambient) +
(amb * gl_FrontMaterial.ambient);
vec3 L = normalize(lightDir);
vec3 D = normalize(spotDirection);
float cos_cur_angle = dot(-L, D);
float cos_inner_cone_angle = cosCut;
float cos_inner_minus_outer_angle =
cos_inner_cone_angle - cos_outer_cone_angle;
float spot = 0.0;
spot = clamp((cos_cur_angle - cos_outer_cone_angle) /
cos_inner_minus_outer_angle, 0.0, 1.0);
vec3 N = normalize(normal);
float lambertTerm = max( dot(N,L), 0.0);
if(lambertTerm > 0.0){
final_color += diff *
exp *
gl_FrontMaterial.diffuse *
lambertTerm * spot;
vec3 E = normalize(eyeVec);
vec3 R = reflect(-L, N);
float specular = pow( max(dot(R, E), 0.0),
gl_FrontMaterial.shininess );
final_color += spec *
gl_FrontMaterial.specular *
specular * spot;
}
gl_FragColor = final_color;
}
如果我正確理解您的代碼和注釋,則球體,光源和照相機位於立方體內部。 這意味着立方體的法線朝外(您正在看其背面),因此點積dot(N,L)
為負,這使lambert_term
等於0
。 這進而導致整個照明計算被跳過。
您有兩個選擇。 修改着色器以照亮背面和正面,或者使用正確面對法線的方式渲染立方體。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.