GLSL写vertex shader和fragment shader
0.一般来说vertex shader处理顶点坐标,然后向后传输,经过光栅化之后,传给fragment shader,其负责颜色、纹理、光照等等。
前者处理之后变成裁剪坐标系(三维),光栅化之后一般认为变成二维的设备坐标系
1.每个顶点有多个属性时的顶点着色器:
1 #version 330 core 2 layout (location = 0) in vec3 aPos; 3 layout (location = 1) in vec3 aColor; 4 layout (location = 2) in vec2 aTexCoord; 5 6 out vec3 ourColor; 7 out vec2 TexCoord; 8 9 void main() 10 { 11 gl_Position = vec4(aPos, 1.0); 12 ourColor = aColor; 13 TexCoord = aTexCoord; 14 }
2.只处理纹理的片元着色器:
1 #version 330 core 2 out vec4 FragColor; 3 4 in vec3 ourColor; 5 in vec2 TexCoord; 6 7 uniform sampler2D ourTexture; 8 9 void main() 10 { 11 FragColor = texture(ourTexture, TexCoord); 12 }
3.将2中的纹理添加之后再加入顶点的颜色,片元着色器咋写呢:
1 #version 330 core 2 out vec4 FragColor; 3 4 in vec3 ourColor; 5 in vec2 TexCoord; 6 7 uniform sampler2D ourTexture; 8 9 void main() 10 { 11 FragColor = texture(ourTexture, TexCoord); 12 FragColor = texture(ourTexture, TexCoord) * vec4(ourColor, 1.0); 13 }
4.渲染多个纹理咋办呢?
1 #version 330 core 2 ... 3 4 uniform sampler2D texture1; 5 uniform sampler2D texture2; 6 7 void main() 8 { 9 FragColor = mix(texture(texture1, TexCoord), texture(texture2, TexCoord), 0.2); 10 }
5.带有坐标变换的顶点着色器
1 #version 330 core 2 layout (location = 0) in vec3 aPos; 3 layout (location = 1) in vec2 aTexCoord; 4 5 out vec2 TexCoord; 6 7 uniform mat4 transform; 8 9 void main() 10 { 11 gl_Position = transform * vec4(aPos, 1.0f); 12 TexCoord = vec2(aTexCoord.x, 1.0 - aTexCoord.y); 13 }
注意照片像素y轴和opengl中纹理坐标的y轴是反向的,所以用个1.0-y,或者加载纹理图片时候可以设置一下std_image库的api,也能解决问题
6.坐标系转换,加入相机后,标准的模型矩阵,观察矩阵,投影矩阵作用下的顶点着色器
1 #version 330 core 2 layout (location = 0) in vec3 aPos; 3 layout (location = 1) in vec2 aTexCoord; 4 5 out vec2 TexCoord; 6 7 uniform mat4 model; 8 uniform mat4 view; 9 uniform mat4 projection; 10 11 void main() 12 { 13 gl_Position = projection * view * model * vec4(aPos, 1.0f); 14 TexCoord = vec2(aTexCoord.x, aTexCoord.y); 15 16 }
7.加入光照和材质的顶点着色器
1 #version 330 core 2 layout (location = 0) in vec3 aPos; 3 layout (location = 1) in vec3 aNormal; 4 5 out vec3 FragPos; 6 out vec3 Normal; 7 8 uniform mat4 model; 9 uniform mat4 view; 10 uniform mat4 projection; 11 12 void main() 13 { 14 FragPos = vec3(model * vec4(aPos, 1.0)); 15 Normal = mat3(transpose(inverse(model))) * aNormal; 16 17 gl_Position = projection * view * vec4(FragPos, 1.0); 18 }
8.加入光照和材质的片元着色器
1 #version 330 core 2 out vec4 FragColor; 3 4 struct Material { 5 vec3 ambient; 6 vec3 diffuse; 7 vec3 specular; 8 float shininess; 9 }; 10 11 struct Light { 12 vec3 position; 13 14 vec3 ambient; 15 vec3 diffuse; 16 vec3 specular; 17 }; 18 19 in vec3 FragPos; 20 in vec3 Normal; 21 22 uniform vec3 viewPos; 23 uniform Material material; 24 uniform Light light; 25 26 void main() 27 { 28 // ambient 29 vec3 ambient = light.ambient * material.ambient; 30 31 // diffuse 32 vec3 norm = normalize(Normal); 33 vec3 lightDir = normalize(light.position - FragPos); 34 float diff = max(dot(norm, lightDir), 0.0); 35 vec3 diffuse = light.diffuse * (diff * material.diffuse); 36 37 // specular 38 vec3 viewDir = normalize(viewPos - FragPos); 39 vec3 reflectDir = reflect(-lightDir, norm); 40 float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess); 41 vec3 specular = light.specular * (spec * material.specular); 42 43 vec3 result = ambient + diffuse + specular; 44 FragColor = vec4(result, 1.0); 45 }
9.带光照纹理贴图的顶点着色器(光照射在纹理贴图上,贴图颜色代表物体颜色)
1 #version 330 core 2 layout (location = 0) in vec3 aPos; 3 layout (location = 1) in vec3 aNormal; 4 layout (location = 2) in vec2 aTexCoords; 5 6 out vec3 FragPos; 7 out vec3 Normal; 8 out vec2 TexCoords; 9 10 uniform mat4 model; 11 uniform mat4 view; 12 uniform mat4 projection; 13 14 void main() 15 { 16 FragPos = vec3(model * vec4(aPos, 1.0)); 17 Normal = mat3(transpose(inverse(model))) * aNormal; 18 TexCoords = aTexCoords; 19 20 gl_Position = projection * view * vec4(FragPos, 1.0); 21 }
10.带光照纹理贴图的片元着色器(光照射在纹理贴图上,贴图颜色代表物体颜色)
1 #version 330 core 2 out vec4 FragColor; 3 4 struct Material { 5 sampler2D diffuse; 6 sampler2D specular; 7 float shininess; 8 }; 9 10 struct Light { 11 vec3 position; 12 13 vec3 ambient; 14 vec3 diffuse; 15 vec3 specular; 16 }; 17 18 in vec3 FragPos; 19 in vec3 Normal; 20 in vec2 TexCoords; 21 22 uniform vec3 viewPos; 23 uniform Material material; 24 uniform Light light; 25 26 void main() 27 { 28 // ambient 29 vec3 ambient = light.ambient * texture(material.diffuse, TexCoords).rgb; 30 31 // diffuse 32 vec3 norm = normalize(Normal); 33 vec3 lightDir = normalize(light.position - FragPos); 34 float diff = max(dot(norm, lightDir), 0.0); 35 vec3 diffuse = light.diffuse * diff * texture(material.diffuse, TexCoords).rgb; 36 37 // specular 38 vec3 viewDir = normalize(viewPos - FragPos); 39 vec3 reflectDir = reflect(-lightDir, norm); 40 float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess); 41 vec3 specular = light.specular * spec * texture(material.specular, TexCoords).rgb; 42 43 vec3 result = ambient + diffuse + specular; 44 FragColor = vec4(result, 1.0); 45 }
11.关于9、10的补充说明:
光照模型其实也分为好多种:平行光(也叫定向光direction light)、点光源(point light)、聚光(spotlight),每种具体的光源渲染细节不同,但是大概结构相似,都满足1中的基本模型解释,只不过在细节和逼真度方面做了调整。具体参看https://learnopengl-cn.github.io/02%20Lighting/05%20Light%20casters/和12
12.带有三种不同光照模型的带纹理的顶点着色器跟片元着色器(终极版)
1 #version 330 core 2 layout (location = 0) in vec3 aPos; 3 layout (location = 1) in vec3 aNormal; 4 layout (location = 2) in vec2 aTexCoords; 5 6 out vec3 FragPos; 7 out vec3 Normal; 8 out vec2 TexCoords; 9 10 uniform mat4 model; 11 uniform mat4 view; 12 uniform mat4 projection; 13 14 void main() 15 { 16 FragPos = vec3(model * vec4(aPos, 1.0)); 17 Normal = mat3(transpose(inverse(model))) * aNormal; 18 TexCoords = aTexCoords; 19 20 gl_Position = projection * view * vec4(FragPos, 1.0); 21 }
1 #version 330 core 2 out vec4 FragColor; 3 4 struct Material { 5 sampler2D diffuse; 6 sampler2D specular; 7 float shininess; 8 }; 9 10 struct DirLight { 11 vec3 direction; 12 13 vec3 ambient; 14 vec3 diffuse; 15 vec3 specular; 16 }; 17 18 struct PointLight { 19 vec3 position; 20 21 float constant; 22 float linear; 23 float quadratic; 24 25 vec3 ambient; 26 vec3 diffuse; 27 vec3 specular; 28 }; 29 30 struct SpotLight { 31 vec3 position; 32 vec3 direction; 33 float cutOff; 34 float outerCutOff; 35 36 float constant; 37 float linear; 38 float quadratic; 39 40 vec3 ambient; 41 vec3 diffuse; 42 vec3 specular; 43 }; 44 45 #define NR_POINT_LIGHTS 4 46 47 in vec3 FragPos; 48 in vec3 Normal; 49 in vec2 TexCoords; 50 51 uniform vec3 viewPos; 52 uniform DirLight dirLight; 53 uniform PointLight pointLights[NR_POINT_LIGHTS]; 54 uniform SpotLight spotLight; 55 uniform Material material; 56 57 // function prototypes 58 vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir); 59 vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir); 60 vec3 CalcSpotLight(SpotLight light, vec3 normal, vec3 fragPos, vec3 viewDir); 61 62 void main() 63 { 64 // properties 65 vec3 norm = normalize(Normal); 66 vec3 viewDir = normalize(viewPos - FragPos); 67 68 // == ===================================================== 69 // Our lighting is set up in 3 phases: directional, point lights and an optional flashlight 70 // For each phase, a calculate function is defined that calculates the corresponding color 71 // per lamp. In the main() function we take all the calculated colors and sum them up for 72 // this fragment's final color. 73 // == ===================================================== 74 // phase 1: directional lighting 75 vec3 result = CalcDirLight(dirLight, norm, viewDir); 76 // phase 2: point lights 77 for(int i = 0; i < NR_POINT_LIGHTS; i++) 78 result += CalcPointLight(pointLights[i], norm, FragPos, viewDir); 79 // phase 3: spot light 80 result += CalcSpotLight(spotLight, norm, FragPos, viewDir); 81 82 FragColor = vec4(result, 1.0); 83 } 84 85 // calculates the color when using a directional light. 86 vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir) 87 { 88 vec3 lightDir = normalize(-light.direction); 89 // diffuse shading 90 float diff = max(dot(normal, lightDir), 0.0); 91 // specular shading 92 vec3 reflectDir = reflect(-lightDir, normal); 93 float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess); 94 // combine results 95 vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords)); 96 vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords)); 97 vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords)); 98 return (ambient + diffuse + specular); 99 } 100 101 // calculates the color when using a point light. 102 vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir) 103 { 104 vec3 lightDir = normalize(light.position - fragPos); 105 // diffuse shading 106 float diff = max(dot(normal, lightDir), 0.0); 107 // specular shading 108 vec3 reflectDir = reflect(-lightDir, normal); 109 float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess); 110 // attenuation 111 float distance = length(light.position - fragPos); 112 float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance)); 113 // combine results 114 vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords)); 115 vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords)); 116 vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords)); 117 ambient *= attenuation; 118 diffuse *= attenuation; 119 specular *= attenuation; 120 return (ambient + diffuse + specular); 121 } 122 123 // calculates the color when using a spot light. 124 vec3 CalcSpotLight(SpotLight light, vec3 normal, vec3 fragPos, vec3 viewDir) 125 { 126 vec3 lightDir = normalize(light.position - fragPos); 127 // diffuse shading 128 float diff = max(dot(normal, lightDir), 0.0); 129 // specular shading 130 vec3 reflectDir = reflect(-lightDir, normal); 131 float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess); 132 // attenuation 133 float distance = length(light.position - fragPos); 134 float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance)); 135 // spotlight intensity 136 float theta = dot(lightDir, normalize(-light.direction)); 137 float epsilon = light.cutOff - light.outerCutOff; 138 float intensity = clamp((theta - light.outerCutOff) / epsilon, 0.0, 1.0); 139 // combine results 140 vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords)); 141 vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords)); 142 vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords)); 143 ambient *= attenuation * intensity; 144 diffuse *= attenuation * intensity; 145 specular *= attenuation * intensity; 146 return (ambient + diffuse + specular); 147 }