- 左边用了gamma,右边没有用gamma

- 顶点着色器
export var vs_gamma_correction =
`#version 300 es
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;
layout (location = 2) in vec2 aTexCoords;
out vec3 FragPos;
out vec3 Normal;
out vec2 TexCoords;
uniform mat4 projection;
uniform mat4 view;
void main(void)
{
FragPos = aPos;
Normal = aNormal;
TexCoords = aTexCoords;
gl_Position = projection * view * vec4(aPos, 1.0);
}`
export var fs_gamma_correction =
`#version 300 es
precision mediump float;
out vec4 FragColor;
in vec3 FragPos;
in vec3 Normal;
in vec2 TexCoords;
uniform sampler2D floorTexture;
uniform vec3 lightPositions[4];
uniform vec3 lightColors[4];
uniform vec3 viewPos;
uniform bool gamma;
vec3 BlinnPhong(vec3 normal, vec3 fragPos, vec3 lightPos, vec3 lightColor)
{
// diffuse 与视角无关 与光线和法线有关
vec3 lightDir = normalize(lightPos - fragPos);
float diff = max(dot(lightDir, normal), 0.0);
vec3 diffuse = diff * lightColor;
// specular 与视角和法线和光线都有关
vec3 viewDir = normalize(viewPos - fragPos);
vec3 reflectDir = reflect(-lightDir, normal);
float spec = 0.0;
vec3 halfwayDir = normalize(lightDir + viewDir);
spec = pow(max(dot(normal, halfwayDir), 0.0), 64.0);
vec3 specular = spec * lightColor;
// simple attenuation 淡出的distance
float max_distance = 1.5;
float distance = length(lightPos - fragPos);
float attenuation = 1.0 / (gamma ? distance * distance : distance);
diffuse *= attenuation; //diffuse和specualr都乘上了
specular *= attenuation;
return diffuse + specular;
}
void main()
{
vec3 color = texture(floorTexture, TexCoords).rgb; //底板颜色
vec3 lighting = vec3(0.0);
for(int i = 0; i < 4; ++i) //四个灯
lighting += BlinnPhong(normalize(Normal), FragPos, lightPositions[i], lightColors[i]);
color *= lighting; //
if(gamma)
color = pow(abs(color), vec3(1.0/2.2)); //直接pow呢
FragColor = vec4(color, 1.0);
}`
let floorTexture = loadTexture("../../textures/wood.png", 4, false);
let floorTextureGammaCorrected = loadTexture("../../textures/wood.png", 4, true);
function loadTexture(url, nrComponents, gammaCorrection) {
const textureID = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, textureID);
const level = 0;
const srcType = gl.UNSIGNED_BYTE;
const pixel = new Uint8Array([0, 0, 255, 255]);
gl.texImage2D(gl.TEXTURE_2D, level, gl.RGBA, 1, 1, 0, gl.RGBA, srcType, pixel);
const image = new Image();
image.onload = function () {
let internalFormat;
let dataFormat;
if (nrComponents == 1) {
internalFormat = dataFormat = gl.RED;
}
else if (nrComponents == 3) {
internalFormat = gammaCorrection ? gl.SRGB : gl.RGB;
dataFormat = gl.RGB;
}
else if (nrComponents == 4) {
internalFormat = gammaCorrection ? gl.SRGB8_ALPHA8 : gl.RGBA8;
dataFormat = gl.RGBA;
}
gl.bindTexture(gl.TEXTURE_2D, textureID);
gl.texImage2D(gl.TEXTURE_2D, 0, internalFormat, image.naturalWidth, image.naturalHeight, 0, dataFormat, gl.UNSIGNED_BYTE, image);
gl.generateMipmap(gl.TEXTURE_2D);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
};
image.src = url;
return textureID;
}
let shader = null;
let glPlaneVAO = 0;
let lightPositions = null;
let lightColors = null;
let projection = mat4.create(), view = mat4.create();
let camera = new Camera(vec3.fromValues(0.0, 0.0, 3.0), vec3.fromValues(0.0, 1.0, 0.0));
let deltaTime = 0.0;
let lastFrame = 0.0;
gl.enable(gl.DEPTH_TEST);
gl.enable(gl.BLEND);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
shader = new Shader(gl, vs_gamma_correction, fs_gamma_correction);
let planeVertices = [
10.0, -0.5, 10.0, 0.0, 1.0, 0.0, 10.0, 0.0,
-10.0, -0.5, 10.0, 0.0, 1.0, 0.0, 0.0, 0.0,
-10.0, -0.5, -10.0, 0.0, 1.0, 0.0, 0.0, 10.0,
10.0, -0.5, 10.0, 0.0, 1.0, 0.0, 10.0, 0.0,
-10.0, -0.5, -10.0, 0.0, 1.0, 0.0, 0.0, 10.0,
10.0, -0.5, -10.0, 0.0, 1.0, 0.0, 10.0, 10.0
];
const POSITION_LOCATION = 0;
const NORMAL_LOCATION = 1;
const TEXCOORD_0_LOCATION = 2;
const sizeFloat = 4;
glPlaneVAO = gl.createVertexArray();
let planeVBO = gl.createBuffer();
gl.bindVertexArray(glPlaneVAO);
gl.bindBuffer(gl.ARRAY_BUFFER, planeVBO);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(planeVertices), gl.STATIC_DRAW);
gl.enableVertexAttribArray(POSITION_LOCATION);
gl.vertexAttribPointer(POSITION_LOCATION, 3, gl.FLOAT, false, 8 * sizeFloat, 0);
gl.enableVertexAttribArray(NORMAL_LOCATION);
gl.vertexAttribPointer(NORMAL_LOCATION, 3, gl.FLOAT, false, 8 * sizeFloat, (3 * sizeFloat));
gl.enableVertexAttribArray(TEXCOORD_0_LOCATION);
gl.vertexAttribPointer(TEXCOORD_0_LOCATION, 2, gl.FLOAT, false, 8 * sizeFloat, (6 * sizeFloat));
gl.bindVertexArray(null);
floorTexture = loadTexture("../../textures/wood.png", 4, false);
floorTextureGammaCorrected = loadTexture("../../textures/wood.png", 4, true);
shader.use(gl);
let floorTextureLocation = gl.getUniformLocation(shader.programId, "floorTexture");
gl.uniform1i(floorTextureLocation, 0);
lightPositions = new Float32Array([
-3.0, 0.0, 0.0,
-1.0, 0.0, 0.0,
1.0, 0.0, 0.0,
3.0, 0.0, 0.0
]);
lightColors = new Float32Array([
0.25, 0.25, 0.25,
0.50, 0.50, 0.50,
0.75, 0.75, 0.75,
1.00, 1.00, 1.00
]);
function render(vao, shader) {
let currentFrame = performance.now();
deltaTime = currentFrame - lastFrame;
lastFrame = currentFrame;
processInput();
gl.clearColor(0.1, 0.1, 0.1, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
shader.use(gl);
mat4.perspective(projection, (camera.Zoom) * Math.PI / 180, canvas.width / canvas.height, 0.1, 100.0);
view = camera.GetViewMatrix();
gl.uniformMatrix4fv(gl.getUniformLocation(shader.programId, "projection"), false, projection);
gl.uniformMatrix4fv(gl.getUniformLocation(shader.programId, "view"), false, view);
gl.uniform3fv(gl.getUniformLocation(shader.programId, "lightPositions"), lightPositions);
gl.uniform3fv(gl.getUniformLocation(shader.programId, "lightColors"), lightColors);
gl.uniform3fv(gl.getUniformLocation(shader.programId, "viewPos"), camera.Position);
gl.uniform1i(gl.getUniformLocation(shader.programId, "gamma"), gammaEnabled ? 1 : 0);
gl.bindVertexArray(glPlaneVAO);
gl.activeTexture(gl.TEXTURE0);
let floorTex = gammaEnabled ? floorTextureGammaCorrected : floorTexture;
gl.bindTexture(gl.TEXTURE_2D, floorTex);
gl.drawArrays(gl.TRIANGLES, 0, 6);
}