本文主要是介绍Modern OpenGL :光照shader,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
Modern OpenGL :光照shader
- 1. 前言
- 2. 数学背景
- 3. 实现
1. 前言
采用shader实现了标准? 冯氏光照模型。
2. 数学背景
老生长谈了。
- 光照模型:冯氏光照模型(环境光+漫反射+镜面反射)
- 光源类型:点光源
环境光通常是一个常量
a m b i e n t = C a ambient= C_{a} ambient=Ca
漫反射与面的法向量N和光线向量L有关
d i f f u s e = C d ∗ m a x ( d o t ( N , L ) , 0 ) diffuse = C_{d} * max (dot (N , L),0) diffuse=Cd∗max(dot(N,L),0)
镜面反射与面的法向量N和光线向量L以及视线向量V有关
s p e c u l a r = C s ∗ m a x ( d o t ( V , r e f l e c t ( − L , N ) ) , 0 ) s h i n i n e s s specular = C_{s} * max (dot (V , reflect(-L,N)),0)^{shininess} specular=Cs∗max(dot(V,reflect(−L,N)),0)shininess
不同于平行光,点光源还有一个属性。其光照强度随距离D缩减
a t t e n u a t i o n = 1 D 2 attenuation = \frac{1}{D^2} attenuation=D21
但是此公式在物体及其接近光源的时候亮度会及其高,因此一般采用如下变种
a t t e n u a t i o n = 1 C + A ∗ D + B ∗ D 2 attenuation = \frac{1}{C + A*D + B* D^2} attenuation=C+A∗D+B∗D21
3. 实现
矩阵库是我自己的渣渣实现这里就不献丑放出来了,读者用glm就可以了。
特别地,当我使用vec3.data()、mat4.data()时,意指获取储存在当前向量或矩阵的元素的数组指针。
顶点类型
class vertex
{
public:vec3 position;vec3 normal;vec2 coord;vec4 color;
};
顶点着色器
#version 430layout (location = 0) uniform mat4 pvm;
layout (location = 1) uniform mat4 model;layout (location = 0) in vec3 position;
layout (location = 1) in vec3 normal;
layout (location = 2) in vec2 coord;
layout (location = 3) in vec4 color;struct v2f{vec3 normal;vec2 coord;vec4 color;vec3 position;
};out v2f vert_out;void main(){vec4 position_ = vec4(position,1);vert_out.normal = mat3(transpose(inverse(model))) * normal;vert_out.coord = coord;vert_out.color = color;vert_out.position = (model * position_).xyz;gl_Position = pvm * position_;
}
片段着色器
#version 430//layout (location = 1) uniform sampler2D sampler;
layout (location = 2) uniform vec4 light_position;
layout (location = 3) uniform vec4 light_ambient;
layout (location = 4) uniform vec4 light_diffuse;
layout (location = 5) uniform vec4 light_specular;
layout (location = 6) uniform vec3 eye;float specular_intensity = 32.0;out vec4 o;struct v2f{vec3 normal;vec2 coord;vec4 color;vec3 position;
};in v2f vert_out;void main() {vec3 normal = normalize(vert_out.normal);vec3 ambient = light_ambient.xyz;vec3 light_direction = normalize(light_position.xyz - vert_out.position);float diffuse_factor = dot(normal,light_direction);vec3 diffuse = vec3(0,0,0);vec3 specular = vec3(0,0,0);if (diffuse_factor > 0){diffuse = light_diffuse.xyz * diffuse_factor ;vec3 vertex_eye = normalize(eye -vert_out.position );vec3 light_reflect = normalize(reflect(-light_direction, normal));float specular_factor = dot(vertex_eye,light_reflect);if (specular_factor > 0) {specular_factor = pow(specular_factor, specular_intensity);specular = light_specular.xyz * specular_factor;}}float distance = length(light_position.xyz - vert_out.position);float attenuation = 10.0 / ( 1 + (distance*distance)); o = vert_out.color * vec4(ambient + (diffuse + specular) *attenuation,1);
}
全部实现
vec4 light_position = vec4(1, -1, 3, 0);
vec4 light_ambient(0.2, 0.2,0.2, 1);
vec4 light_diffuse(0.5, 0.5, 0.5,1);
vec4 light_specular(0.5, 0.5,0.5, 1);
vec3 eye(0, -3,3);mat4 view = mat4::view(eye, vec3(0,0,0), vec3(0,1 ,0));
mat4 model_1(1.0);
mat4 model_2 = mat4::translate(0,0,0.5);
mat4 persp = matrix4::perspective(45.0*math::PId180, 800.0F/600.0F, 1.0F,1000.0f);GLuint plane_vao;
GLuint cube_vao;
GLuint plane_vbo;
GLuint cube_vbo;
GLuint plane_ebo;
GLuint cube_ebo;
GLuint plane_ebo_size;
GLuint cube_ebo_size;
GLuint sphere_vao;
GLuint sphere_vbo;
GLuint sphere_ebo;
GLuint sphere_ebo_size;
GLuint shader_vert;
GLuint shader_frag;
GLuint program;string vertex_shader =
R"(
#version 430layout (location = 0) uniform mat4 pvm;
layout (location = 1) uniform mat4 model;layout (location = 0) in vec3 position;
layout (location = 1) in vec3 normal;
layout (location = 2) in vec2 coord;
layout (location = 3) in vec4 color;struct v2f{vec3 normal;vec2 coord;vec4 color;vec3 position;
};out v2f vert_out;void main(){vec4 position_ = vec4(position,1);vert_out.normal = mat3(transpose(inverse(model))) * normal;vert_out.coord = coord;vert_out.color = color;vert_out.position = (model * position_).xyz;gl_Position = pvm * position_;
}
)";string fragment_shader =
R"(
#version 430//layout (location = 1) uniform sampler2D sampler;
layout (location = 2) uniform vec4 light_position;
layout (location = 3) uniform vec4 light_ambient;
layout (location = 4) uniform vec4 light_diffuse;
layout (location = 5) uniform vec4 light_specular;
layout (location = 6) uniform vec3 eye;float specular_intensity = 32.0;out vec4 o;struct v2f{vec3 normal;vec2 coord;vec4 color;vec3 position;
};in v2f vert_out;void main() {vec3 normal = normalize(vert_out.normal);vec3 ambient = light_ambient.xyz;vec3 light_direction = normalize(light_position.xyz - vert_out.position);float diffuse_factor = dot(normal,light_direction);vec3 diffuse = vec3(0,0,0);vec3 specular = vec3(0,0,0);if (diffuse_factor > 0){diffuse = light_diffuse.xyz * diffuse_factor ;vec3 vertex_eye = normalize(eye -vert_out.position );vec3 light_reflect = normalize(reflect(-light_direction, normal));float specular_factor = dot(vertex_eye,light_reflect);if (specular_factor > 0) {specular_factor = pow(specular_factor, specular_intensity);specular = light_specular.xyz * specular_factor;}}float distance = length(light_position.xyz - vert_out.position);float attenuation = 10.0 / ( 1 + (distance*distance)); o = vert_out.color * vec4(ambient + (diffuse + specular) *attenuation,1);
})";void resource_init()
{glEnable(GL_DEPTH_TEST);glCullFace(GL_BACK);glEnable(GL_CULL_FACE);glClearColor(0.f, 0.f, .3f, 1.f);glViewport(0, 0, 800, 600);vector<vertex> vertices ={{{-10,-10,0},{0,0,1},{0,0},{0.5,0.5,0.5,1}},{{10,-10,0},{0,0,1},{1,0},{0.5,0.5,0.5,1}},{ {10,10,0},{0,0,1},{1,1},{0.5,0.5,0.5,1}},{{-10,10,0},{0,0,1},{0,1},{0.5,0.5,0.5,1}},};vector<GLuint> indices = {0,1,2,0,2,3,};glGenVertexArrays(1, &plane_vao);glGenBuffers(1, &plane_vbo);glGenBuffers(1, &plane_ebo);glBindVertexArray(plane_vao);glBindBuffer(GL_ARRAY_BUFFER, plane_vbo);glBufferData(GL_ARRAY_BUFFER, sizeof(vertex)*vertices.size(), vertices.data(), GL_STATIC_DRAW);glEnableVertexAttribArray(0);glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(vertex), (const void*)(0));glEnableVertexAttribArray(1);glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(vertex), (const void*)(sizeof(float[3])));glEnableVertexAttribArray(2);glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(vertex), (const void*)(sizeof(float[6])));glEnableVertexAttribArray(3);glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, sizeof(vertex), (const void*)(sizeof(float[8])));glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, plane_ebo);plane_ebo_size = indices.size();glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)*plane_ebo_size, indices.data(), GL_STATIC_DRAW);vertices ={{{-0.5,-0.5,0.5},{0,0,1},{0,0},{1,1,1,1}},{{0.5,-0.5,0.5},{0,0,1},{1,0},{1,1,1,1}},{{0.5,0.5,0.5},{0,0,1},{1,1},{1,1,1,1}},{{-0.5,0.5,0.5},{0,0,1},{0,1},{1,1,1,1}},{{-0.5,-0.5,-0.5},{0,0,-1},{0,0},{1,1,1,1}},{{-0.5,0.5,-0.5},{0,0,-1},{0,1},{1,1,1,1}},{{0.5,0.5,-0.5},{0,0,-1},{1,1},{1,1,1,1}},{{0.5,-0.5,-0.5},{0,0,-1},{1,0},{1,1,1,1}},{{-0.5,-0.5,0.5},{0,-1,0},{0,0},{1,1,1,1}},{{-0.5,-0.5,-0.5},{0,-1,0},{1,0},{1,1,1,1}},{{0.5,-0.5,-0.5},{0,-1,0},{1,1},{1,1,1,1}},{{0.5,-0.5,0.5},{0,-1,0},{0,1},{1,1,1,1}},{{0.5,-0.5,0.5},{1,0,0},{0,0},{1,1,1,1}},{{0.5,-0.5,-0.5},{1,0,0},{1,0},{1,1,1,1}},{{0.5,0.5,-0.5},{1,0,0},{1,1},{1,1,1,1}},{{0.5,0.5,0.5},{1,0,0},{0,1},{1,1,1,1}},{{0.5,0.5,0.5},{0,1,0},{0,0},{1,1,1,1}},{{0.5,0.5,-0.5},{0,1,0},{1,0},{1,1,1,1}},{{-0.5,0.5,-0.5},{0,1,0},{1,1},{1,1,1,1}},{{-0.5,0.5,0.5},{0,1,0},{0,1},{1,1,1,1}},{{-0.5,0.5,0.5},{-1,0,0},{0,0},{1,1,1,1}},{{-0.5,0.5,-0.5},{-1,0,0},{1,0},{1,1,1,1}},{{-0.5,-0.5,-0.5},{-1,0,0},{1,1},{1,1,1,1}},{{-0.5,-0.5,0.5},{-1,0,0},{0,1},{1,1,1,1}},};indices ={0,1,2,0,2,3,4,5,6,4,6,7,8,9,10,8,10,11,12,13,14,12,14,15,16,17,18,16,18,19,20,21,22,20,22,23,};glGenVertexArrays(1, &cube_vao);glGenBuffers(1, &cube_vbo);glGenBuffers(1, &cube_ebo);glBindVertexArray(cube_vao);glBindBuffer(GL_ARRAY_BUFFER, cube_vbo);glBufferData(GL_ARRAY_BUFFER, sizeof(vertex)*vertices.size(), vertices.data(), GL_STATIC_DRAW);glEnableVertexAttribArray(0);glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(vertex), (const void*)(0));glEnableVertexAttribArray(1);glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(vertex), (const void*)(sizeof(float[3])));glEnableVertexAttribArray(2);glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(vertex), (const void*)(sizeof(float[6])));glEnableVertexAttribArray(3);glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, sizeof(vertex), (const void*)(sizeof(float[8])));glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cube_ebo);cube_ebo_size = indices.size();glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)*cube_ebo_size, indices.data(), GL_STATIC_DRAW);glBindVertexArray(0);GLint compiled = GL_FALSE;shader_vert = glCreateShader(GL_VERTEX_SHADER);const GLchar* src = reinterpret_cast<const GLchar*>(vertex_shader.data());glShaderSource(shader_vert, 1, &src, NULL);glCompileShader(shader_vert);shader_frag = glCreateShader(GL_FRAGMENT_SHADER);src = reinterpret_cast<const GLchar*>(fragment_shader.data());glShaderSource(shader_frag, 1, &src, NULL);glCompileShader(shader_frag);program = glCreateProgram();glAttachShader(program , shader_vert);glAttachShader(program , shader_frag);glLinkProgram(program );GLint size;glGetProgramiv(program , GL_INFO_LOG_LENGTH, &size);if (size > 0) {xgc::list<char> str(size);GLint len;glGetProgramInfoLog(program , size, &len, str.data());cout << str.data() << endl;}}float rotate_ = 0.0;void _Render()
{glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);rotate_ += 0.01f;//vec4 light_position = (-vec4(cos(rotate_), sin(rotate_), 1, 0)) .normalize();auto R = mat4::rotate(vec3(1, 0, 0), rotate_);glUseProgram(program );glUniform4fv(2, 1, light_position.data());glUniform4fv(3, 1, light_ambient.data());glUniform4fv(4, 1, light_diffuse.data());glUniform4fv(5, 1, light_specular.data());glUniform3fv(6, 1, eye.data());auto pvm = persp * view * model_1;glUniformMatrix4fv(0, 1, GL_FALSE, pvm.data());glUniformMatrix4fv(1, 1, GL_FALSE, model_1.data());glBindVertexArray(plane_vao);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, plane_ebo);glDrawElements(GL_TRIANGLES, plane_ebo_size, GL_UNSIGNED_INT, NULL);auto _model = model_2 * R;pvm = persp * view * _model;glUniformMatrix4fv(0, 1, GL_FALSE, pvm.data());glUniformMatrix4fv(1, 1, GL_FALSE, _model.data());glBindVertexArray(cube_vao);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cube_ebo);glDrawElements(GL_TRIANGLES, cube_ebo_size, GL_UNSIGNED_INT, NULL);
}int main(int argc, char** argv, char** envp)
{auto hr = glfwInit();glfwSetErrorCallback(error_callback);glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); // OpenGL主版本号glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); // OpenGL副版本号glfwWindowHint(GLFW_RESIZABLE, GL_TRUE); //可改变大小 glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);hwnd = glfwCreateWindow(800, 600, "GLFW Window", NULL, NULL);glfwSetInputMode(hwnd, GLFW_RAW_MOUSE_MOTION, GLFW_TRUE);glfwMakeContextCurrent(hwnd);glfwSwapInterval(1);glfwSetFramebufferSizeCallback(hwnd, (GLFWframebuffersizefun)size_changed);glfwSetKeyCallback(hwnd, (GLFWkeyfun)key_board);glfwSetMouseButtonCallback(hwnd, MouseEvent);glfwSetScrollCallback(hwnd, MouseScrollEvent);auto err = glewInit();if (GLEW_OK != err) {std::cerr << "GLEW Error : " << glewGetErrorString(err) << std::endl;return err;}resource_init();while (!glfwWindowShouldClose(hwnd)) {_Render();glfwSwapBuffers(hwnd); glfwPollEvents();}glfwDestroyWindow(hwnd);glfwTerminate();return 0;
}
这篇关于Modern OpenGL :光照shader的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!