java - 使用处理实现 GLSL 着色器以进行聚光灯
问题描述
我目前正在使用 Gouraud 和 Phong 简单着色器和 PointLights。但是,相反,我想介绍多个 SPOTLIGHT 来源。但我不确定我应该对我的新片段和顶点着色器进行哪些更改。
这是我目前的 GLSL 程序:
片段.glsl
#ifdef GL_ES
precision mediump float;
precision mediump int;
#endif
varying vec4 col;
void main() {
gl_FragColor = col;
}
顶点.glsl
#define PROCESSING_LIGHT_SHADER
uniform mat4 modelview;
uniform mat4 transform;
uniform mat3 normalMatrix;
uniform vec4 lightPosition;
attribute vec4 vertex;
attribute vec4 color;
attribute vec3 normal;
varying vec4 col;
void main(){
gl_Position = transform*vertex;
vec3 vertexCamera = vec3(modelview * vertex);
vec3 transformedNormal = normalize(normalMatrix * normal);
vec3 dir = normalize(lightPosition.xyz - vertexCamera);
float light = max(0.0, dot(dir, transformedNormal));
col = vec4(light, light, light, 1)*color;
}
解决方案
在处理过程中,您最多可以使用 8 个光源。要访问光源,您必须声明具有数组类型的Uniform,如处理光着色器教程中所述:
uniform vec4 lightPosition[8];
在应用程序中设置多个光源(例如2个):
pointLight(255, 255, 255, width/2, height, 200);
pointLight(255, 255, 255, width, height/2, 200);
遍历(2)个光源,并在着色器程序中总结光。例如:
void main() {
gl_Position = transform * position;
vec3 ecPosition = vec3(modelview * position);
vec3 ecNormal = normalize(normalMatrix * normal);
vertColor = vec4(0.0);
for (int i=0; i < 2; ++i)
{
vec3 direction = normalize(lightPosition[i].xyz - ecPosition);
float intensity = max(0.0, dot(direction, ecNormal));
vertColor += vec4(intensity, intensity, intensity, 1) * color;
}
}
带有绿色和红色点灯的示例:
应用程序
PShape can;
float angle;
PShader lightShader;
void setup() {
size(640, 360, P3D);
can = createCan(100, 200, 32);
lightShader = loadShader("lightfrag.glsl", "lightvert.glsl");
}
void draw() {
background(0);
shader(lightShader);
pointLight(0, 255, 0, width/2, height, 200);
pointLight(255, 0, 0, width, height/2, 200);
translate(width/2, height/2);
rotateY(angle);
shape(can);
angle += 0.01;
}
PShape createCan(float r, float h, int detail) {
textureMode(NORMAL);
PShape sh = createShape();
sh.beginShape(QUAD_STRIP);
sh.noStroke();
for (int i = 0; i <= detail; i++) {
float angle = TWO_PI / detail;
float x = sin(i * angle);
float z = cos(i * angle);
float u = float(i) / detail;
sh.normal(x, 0, z);
sh.vertex(x * r, -h/2, z * r, u, 0);
sh.vertex(x * r, +h/2, z * r, u, 1);
}
sh.endShape();
return sh;
}
顶点着色器
uniform mat4 modelview;
uniform mat4 transform;
uniform mat3 normalMatrix;
uniform vec4 lightPosition[8];
uniform vec3 lightDiffuse[8];
attribute vec4 position;
attribute vec4 color;
attribute vec3 normal;
varying vec4 vertColor;
void main() {
gl_Position = transform * position;
vec3 ecPosition = vec3(modelview * position);
vec3 ecNormal = normalize(normalMatrix * normal);
vertColor = vec4(0.0);
for (int i=0; i < 2; ++i)
{
vec3 direction = normalize(lightPosition[i].xyz - ecPosition);
float intensity = max(0.0, dot(direction, ecNormal));
vertColor += vec4(intensity * lightDiffuse[i], 1.0) * color;
}
}
片段着色器
#ifdef GL_ES
precision mediump float;
precision mediump int;
#endif
varying vec4 vertColor;
void main() {
gl_FragColor = vertColor;
}
推荐阅读
- reactjs - 将纹理图像加载到平面(上下文丢失)
- python - BeautifulSoup 无法从表中获取链接
- angular - 在 Chrome 上使用 Shaka Player 播放 HLS m3u8
- python - 重塑 4D Numpy 图像数据
- python - Pandas Dataframe:基于字典列表更新多行的最快方法
- java - 根据代码中的某些条件优雅地将对象添加到 HashMap
- c++ - 如何以 API 兼容的方式重命名类成员?
- ios - 是否有公开的 API 来生成 Firestore ID(在 Swift 中)
- c++ - 是否可以使用带线程的 OpenCV 加速 C++ 程序?(在覆盆子 A3+ 上)
- java - IntelliJ IDEA Maven 项目运行调试配置时出现 StackOverflowError