GLSL技术咨询:如何获取当前片段纹理颜色及实现片段颜色叠加
Hey there! No worries at all—GLSL can feel a bit overwhelming when you're just starting out, so let's break down your two questions step by step and tweak your shader to fit what you need.
To get the texture color for the current fragment, you'll need to add a few key pieces to both your vertex and fragment shader:
Pass texture coordinates from the vertex shader:
In your vertex shader, add avaryingvariable to carry texture coordinates over to the fragment shader:varying vec2 vTexCoord; void main() { // ... keep your existing vertex shader logic ... vTexCoord = gl_MultiTexCoord0.xy; // Pass the default texture coordinates from the vertex gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; }Sample the texture in the fragment shader:
First, declare auniformto reference your texture asset, plus thevaryingcoordinate variable. Add these lines at the top of your fragment shader:uniform sampler2D texture; // Links to your game's texture asset varying vec2 vTexCoord; // Receives coordinates from the vertex shaderThen, inside the
main()function, use thetexture2D()function to grab the color at the current fragment's coordinates:vec4 texColor = texture2D(texture, vTexCoord);
Color overlay (blending) has several common modes—let's cover a few easy-to-implement options that you can swap into your shader, using the texture color and your existing finalColor (the lighting calculation result):
模式1:简单加法叠加(Brightening effect)
Add the lighting color to the texture color, then clamp the result to keep values within valid 0.0–1.0 color range:
gl_FragColor = clamp(texColor + finalColor, 0.0, 1.0);
模式2:乘法叠加(Tinting/Darkening effect)
Multiply the texture color by the lighting color to tint the texture with your calculated lighting:
gl_FragColor = texColor * finalColor;
模式3:屏幕叠加(High-contrast brightening)
This mode brightens the texture while preserving highlights, similar to shining a light through a transparent layer:
gl_FragColor = 1.0 - (1.0 - texColor) * (1.0 - finalColor);
模式4:标准Overlay混合(Photoshop-style)
This combines multiplication and screen blending based on the texture's brightness, creating a vibrant, high-contrast effect:
vec4 overlayColor; // Apply multiply for dark texture channels, screen for bright ones overlayColor.r = texColor.r <= 0.5 ? 2.0 * texColor.r * finalColor.r : 1.0 - 2.0 * (1.0 - texColor.r) * (1.0 - finalColor.r); overlayColor.g = texColor.g <= 0.5 ? 2.0 * texColor.g * finalColor.g : 1.0 - 2.0 * (1.0 - texColor.g) * (1.0 - finalColor.g); overlayColor.b = texColor.b <= 0.5 ? 2.0 * texColor.b * finalColor.b : 1.0 - 2.0 * (1.0 - texColor.b) * (1.0 - finalColor.b); overlayColor.a = texColor.a * finalColor.a; // Preserve alpha channel gl_FragColor = overlayColor;
Here's your shader updated with texture sampling and the screen overlay mode (swap in any of the other modes above if you prefer):
varying vec3 vN; varying vec3 v; varying vec4 color; uniform sampler2D texture; // Add texture reference varying vec2 vTexCoord; // Add texture coordinate variable #define MAX_LIGHTS 1 void main (void) { vec3 N = normalize(vN); vec4 finalColor = vec4(0.0, 0.0, 0.0, 0.0); // Keep your existing lighting calculation logic for (int i=0;i<MAX_LIGHTS;i++) { vec3 L = normalize(gl_LightSource[i].position.xyz - v); vec3 E = normalize(-v); vec3 R = normalize(-reflect(L,N)); vec4 Iamb = gl_LightSource[i].ambient; vec4 Idiff = gl_LightSource[i].diffuse * max(dot(N,L), 0.0); Idiff = clamp(Idiff, 0.0, 1.0); vec4 Ispec = gl_LightSource[i].specular * pow(max(dot(R,E),0.0),0.3*gl_FrontMaterial.shininess); Ispec = clamp(Ispec, 0.0, 1.0); finalColor += Iamb + Idiff + Ispec; } // Get the current fragment's texture color vec4 texColor = texture2D(texture, vTexCoord); // Apply screen overlay blend gl_FragColor = 1.0 - (1.0 - texColor) * (1.0 - finalColor); // Swap with another mode example: gl_FragColor = texColor * finalColor; }
Quick reminder: Don't forget to bind your game's texture asset to the texture uniform in your game code—this tells the shader which texture to sample from!
内容的提问来源于stack exchange,提问作者user15922830

