2012-03-20 21 views
16

Chiếu sáng dựa trên pixel là một vấn đề phổ biến trong nhiều ứng dụng OpenGL, vì ánh sáng OpenGL tiêu chuẩn có chất lượng rất kém.Đèn chiếu sáng GLSL chung

Tôi muốn sử dụng chương trình GLSL để có ánh sáng dựa trên mỗi pixel trong chương trình OpenGL của tôi thay vì cho mỗi đỉnh. Chỉ cần khuếch tán ánh sáng, nhưng với sương mù, kết cấu và texture-alpha ít nhất.

tôi bắt đầu với this shader:

texture.vert:

varying vec3 position; 
varying vec3 normal; 

void main(void) 
{ 
    gl_Position  = gl_ModelViewProjectionMatrix * gl_Vertex; 
    gl_FrontColor  = gl_Color; 
    gl_TexCoord[0] = gl_MultiTexCoord0; 
    normal  = normalize(gl_NormalMatrix * gl_Normal); 
    position  = vec3(gl_ModelViewMatrix * gl_Vertex); 
} 

texture.frag:

uniform sampler2D Texture0; 
uniform int ActiveLights; 

varying vec3 position; 
varying vec3 normal; 

void main(void) 
{ 
    vec3 lightDir; 
    float attenFactor; 
    vec3 eyeDir   = normalize(-position); // camera is at (0,0,0) in ModelView space 
    vec4 lightAmbientDiffuse = vec4(0.0,0.0,0.0,0.0); 
    vec4 lightSpecular  = vec4(0.0,0.0,0.0,0.0);  

    // iterate all lights 
    for (int i=0; i<ActiveLights; ++i) 
    { 
    // attenuation and light direction 
    if (gl_LightSource[i].position.w != 0.0) 
    { 
     // positional light source 
     float dist = distance(gl_LightSource[i].position.xyz, position); 
     attenFactor = 1.0/(gl_LightSource[i].constantAttenuation + 
        gl_LightSource[i].linearAttenuation * dist + 
        gl_LightSource[i].quadraticAttenuation * dist * dist); 
     lightDir = normalize(gl_LightSource[i].position.xyz - position); 
    }  
    else 
    {   
     // directional light source   
     attenFactor = 1.0;   
     lightDir = gl_LightSource[i].position.xyz;  
    }  
    // ambient + diffuse   
    lightAmbientDiffuse  += gl_FrontLightProduct[i].ambient*attenFactor;  
    lightAmbientDiffuse  += gl_FrontLightProduct[i].diffuse * max(dot(normal, lightDir), 0.0) * attenFactor; 
    // specular  
    vec3 r  = normalize(reflect(-lightDir, normal)); 
    lightSpecular += gl_FrontLightProduct[i].specular * 
        pow(max(dot(r, eyeDir), 0.0), gl_FrontMaterial.shininess) * 
        attenFactor; 
    }  
    // compute final color  
    vec4 texColor = gl_Color * texture2D(Texture0, gl_TexCoord[0].xy);  
    gl_FragColor = texColor * (gl_FrontLightModelProduct.sceneColor + lightAmbientDiffuse) + lightSpecular; 

    float fog = (gl_Fog.end - gl_FogFragCoord) * gl_Fog.scale; // Intensität berechnen 
    fog  = clamp(fog, 0.0, 1.0);     // Beschneiden 
    gl_FragColor = mix(gl_Fog.color, gl_FragColor, fog);   // Nebelfarbe einmischen 
} 

Bình luận là Đức bởi vì nó là một trang web tiếng Đức nơi mã này đã được đăng , lấy làm tiếc.

Nhưng tất cả công cụ đổ bóng này đều làm mọi thứ rất tối. Không có hiệu ứng ánh sáng ở tất cả - nhưng các mã đổ bóng biên dịch. Nếu tôi chỉ sử dụng GL_LIGHT0 trong trình đổ bóng phân đoạn thì có vẻ như nó hoạt động, nhưng chỉ hợp lý đối với các đa giác đối diện với máy ảnh và đa giác sàn của tôi cực kỳ tối. Ngoài ra quads với RGBA kết cấu cho thấy không có dấu hiệu của sự minh bạch. Tôi sử dụng tiêu chuẩn glRotate/Dịch cho ma trận Modelview và glVertex/Normal cho đa giác của tôi. OpenGL chiếu sáng hoạt động tốt ngoài thực tế là nó trông xấu xí trên bề mặt rất lớn. Tôi gấp ba lần kiểm tra các tiêu chuẩn của tôi, họ ổn.

Có điều gì sai trong mã ở trên không? HOẶC Hãy cho tôi biết lý do tại sao không có Shader ánh sáng chung cho tác vụ thực tế này (điểm dựa trên ánh sáng với khoảng cách từ xa: nến nếu bạn muốn) - không nên chỉ có một cách chính xác để thực hiện việc này? Tôi không muốn bump/normal/parallax/toon/blur/bất kỳ hiệu ứng nào. Tôi chỉ muốn ánh sáng của tôi hoạt động tốt hơn với các đa giác lớn hơn.

Tất cả các hướng dẫn tôi tìm thấy chỉ hữu ích khi chiếu sáng một đối tượng khi máy ảnh ở vị trí 0,0,0 đối diện trực giao với đối tượng. Ở trên là người duy nhất thấy rằng ít nhất là trông giống như điều tôi muốn làm.

+1

Điều đầu tiên: bạn có ràng buộc một mẫu, là các kết cấu và đường chuẩn của bạn đúng không, liệu nó có hiển thị hình học nếu bạn đặt gl_FragColor thành màu cố định không?Với shaders tôi thấy dễ dàng hơn để có được đầu của tôi xung quanh họ bằng cách sử dụng và thêm các tính năng nhỏ tại một thời điểm, trong trường hợp không có khả năng bước vào và theo dõi qua chúng: p. – Robinson

+0

Sampler là TEXTURE_2D và nó bị ràng buộc các polys kết xuất. Texture coords là chính xác, vì ánh sáng openGL bình thường thực hiện hoàn hảo. Normals là hoàn hảo (như đã nêu). Có nó cho thấy hình học khi thiết lập gl_FragColor thành một màu cố định hoặc chỉ để texColor. – Rock

Trả lời

10

tôi sẽ đề nghị bạn đọc this article để xem cách ADS chuẩn sét được thực hiện trong vòng GLSL.That là GL 4.0 nhưng không phải là một vấn đề để thích nghi với phiên bản của bạn:

Ngoài ra bạn hoạt động trong giao diện (camera) không gian để DON "T phủ nhận con mắt vector:

vec3 eyeDir = normalize(-position); 

tôi có vấn đề khá tương tự như bạn vì tôi cũng phủ nhận vector mắt quên rằng nó được chuyển đổi thành các khuếch tán xem space.Your và tính toán gương dường như là sai trong kịch bản hiện tại. Ở vị trí của bạn, tôi sẽ không sử dụng dữ liệu từ đường ống cố định một cách khôn ngoan những gì là điểm làm nó trong một shader? Dưới đây là phương pháp để tính toán khuếch tán và phản chiếu trong mỗi đoạn ADS điểm sét:

void ads(int lightIndex,out vec3 ambAndDiff, out vec3 spec) 
{ 


vec3 s = vec3(lights[lightIndex].Position - posOut) ; 
vec3 v = normalize(posOut.xyz); 
vec3 n = normalize(normOut); 
vec3 h = normalize(v+s) ;// half vector (read in the web on what it is) 


    vec3 diffuse = ((Ka+ lights[lightIndex].Ld) * Kd * max(0.0,dot(n, v))) ; 
    spec = Ks * pow(max(0.0, dot(n,h)), Shininess) ; 


ambAndDiff = diffuse ; 

/// Ka-material ambient factor 
/// Kd-material diffuse factor 
/// Ks-material specular factor. 
/// lights[lightIndex].Ld-lights diffuse factor;you may also add La and Ls if you want to have even more control of the light shading. 
} 

Ngoài ra tôi sẽ không đề nghị bạn sử dụng các phương trình suy giảm bạn có ở đây, thật khó để control.If bạn muốn thêm sự suy giảm dựa trên bán kính ánh sáng there is this nice blog post: