LearnOpenGL 总结记录<11> Gamma correction

Example:

// render
        // ------
        glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        // draw objects
        shader.use();
        glm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
        glm::mat4 view = camera.GetViewMatrix();
        shader.setMat4("projection", projection);
        shader.setMat4("view", view);
        // set light uniforms
        glUniform3fv(glGetUniformLocation(shader.ID, "lightPositions"), 4, &lightPositions[0][0]);
        glUniform3fv(glGetUniformLocation(shader.ID, "lightColors"), 4, &lightColors[0][0]);
        shader.setVec3("viewPos", camera.Position);
        shader.setInt("gamma", gammaEnabled);
        // floor
        glBindVertexArray(planeVAO);
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, gammaEnabled ? floorTextureGammaCorrected : floorTexture);
        glDrawArrays(GL_TRIANGLES, 0, 6);

PS:

#version 330 core
out vec4 FragColor;

in VS_OUT {
    vec3 FragPos;
    vec3 Normal;
    vec2 TexCoords;
} fs_in;

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
    float max_distance = 1.5;
    float distance = length(lightPos - fragPos);
    float attenuation = 1.0 / (gamma ? distance * distance : distance);
    
    diffuse *= attenuation;
    specular *= attenuation;
    
    return diffuse + specular;
}

void main()
{           
    vec3 color = texture(floorTexture, fs_in.TexCoords).rgb;
    vec3 lighting = vec3(0.0);
    for(int i = 0; i < 4; ++i)
        lighting += BlinnPhong(normalize(fs_in.Normal), fs_in.FragPos, lightPositions[i], lightColors[i]);
    color *= lighting;
    if(gamma)
        color = pow(color, vec3(1.0/2.2));
    FragColor = vec4(color, 1.0);
}

需要注意:这里的floorTextureGammaCorrected 是 sRGB 的Texture,而floorTexture 就是普通的RGB 的Texture。

1. 这里如果开启了 gammaCorrected 的话,就使用 floorTextureGammaCorrected 和执行 shader 中的 

color = pow(color, vec3(1.0/2.2));

如果是 sRGB Texture 的话,那么 会自动 从sRGB 变换 线性,也就是,在shader中,都是拿着线性的数据进行操作的,最后再进行再进行 gamma Correct,抵消 CRT gamma.

If we create a texture in OpenGL with any of these two sRGB texture formats specified, OpenGL will automatically correct the colors to linear-space as soon as we use them, allowing us to properly work in linear space with all color values extracted.

 

2. 关于 

glEnable(GL_FRAMEBUFFER_SRGB);

The first option is probably the easiest, but also gives you less control. By enabling GL_FRAMEBUFFER_SRGB you tell OpenGL that each subsequent drawing commands should first gamma correct colors from the sRGB color space before storing them in color buffer(s). The sRGB is a color space that roughly corresponds to a gamma of 2.2 and a standard for most home devices. After enabling GL_FRAMEBUFFER_SRGB OpenGL will automatically perform gamma correction after each fragment shader run to all subsequent framebuffers, including the default framebuffer.

From now on your rendered images will be gamma corrected and as this is done by the hardware it is completely free. Something you should keep in mind with this approach (and the other approach) is that gamma correction (also) transforms the colors from linear space to non-linear space so it is very important you only do gamma correction at the last and final step. If you gamma-correct your colors before the final output, all subsequent operations on those colors will operate on incorrect values. For instance, if you use multiple framebuffers you probably want intermediate results passed in between framebuffers to remain in linear-space and only have the last framebuffer apply gamma correction before being sent to the monitor.

(openg 打开 GL_FRAMEBUFFER_SRGB 之后,所有的fragment shader 运行之后,自动执行 gamma correction ,再存储到 framebuffer 中

 

参考:

https://blog.csdn.net/aa20274270/article/details/84954179

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
#include<algorithm> #include<iostream> #include<vector> #include<string> #include<cmath> #include <cstdio> #include <map> #include <unordered_map> using namespace std; const int INF = 0x3f3f3f3f; int n, gamma, time_count=0; int time[10]; string alpha; vector<int> Length(50005, 0); unordered_map<string, int> number; unordered_map<int, string> nega_number; vector<unordered_map<int, int>> edge(50005); vector<int> trace(50005, 0); vector<int> final_trace; void finding(string alpha) { int a=number[alpha], b; char beta; string epsilon; for(int i=9; i>=0; i--) { for(int j=1; j<10; j++) { epsilon = alpha; epsilon[i] = '0' + (int(epsilon[i]) + j) % 10; if(number.find(epsilon) != number.end() and epsilon != alpha) { b = number[epsilon]; edge[a][b]= time[i]; } } for(int j=i-1; j>=0; j--) { epsilon = alpha; beta = epsilon[j]; epsilon[j] = epsilon[i]; epsilon[i] = beta; if(number.find(epsilon) != number.end() and epsilon != alpha) { b = number[epsilon]; edge[a][b]= time[j]; } } } } void dijkstra(int i) { int beta; for(auto j : edge[i]) { beta = Length[j.first]; if(beta > Length[i] + j.second) { Length[j.first] = Length[i] + j.second; trace[j.first] = i; if(beta == INF) { dijkstra(j.first); } } } } int main() { cin>>n; for(int i=2; i<n+1;i++) { Length[i] = INF; } for(int i=0; i<10; i++) { cin>>time[i]; } for(int i=0; i<n; i++) { cin>>alpha; nega_number[i] = alpha; number[alpha] = i+1; } for(int i=0; i<n; i++) { alpha = nega_number[i]; finding(alpha); } dijkstra(1); if(Length[n] == INF) { cout<<"-1"; } else { gamma = n; final_trace.push_back(gamma); cout<<Length[n]<<endl; while(gamma != 1) { gamma = trace[gamma]; final_trace.push_back(gamma); } cout<<final_trace.size()<<endl; for(int i=final_trace.size()-1;i>-1;i--) { cout<<final_trace[i]<<" "; } } //system("pause"); return 0; }修改当中的dijkstra
05-28
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值