Modern OpenGL :光照shader

2024-06-16 22:08
文章标签 opengl shader modern 光照

本文主要是介绍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=Cdmax(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=Csmax(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+AD+BD21

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的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1067684

相关文章

OPENGL顶点数组, glDrawArrays,glDrawElements

顶点数组, glDrawArrays,glDrawElements  前两天接触OpenGL ES的时候发现里面没有了熟悉的glBegin(), glEnd(),glVertex3f()函数,取而代之的是glDrawArrays()。有问题问google,终于找到答案:因为OpenGL ES是针对嵌入式设备这些对性能要求比较高的平台,因此把很多影响性能的函数都去掉了,上述的几个函数都被移除了。接

OpenGL ES学习总结:基础知识简介

什么是OpenGL ES? OpenGL ES (为OpenGL for Embedded System的缩写) 为适用于嵌入式系统的一个免费二维和三维图形库。 为桌面版本OpenGL 的一个子集。 OpenGL ES管道(Pipeline) OpenGL ES 1.x 的工序是固定的,称为Fix-Function Pipeline,可以想象一个带有很多控制开关的机器,尽管加工

OpenGL雾(fog)

使用fog步骤: 1. enable. glEnable(GL_FOG); // 使用雾气 2. 设置雾气颜色。glFogfv(GL_FOG_COLOR, fogColor); 3. 设置雾气的模式. glFogi(GL_FOG_MODE, GL_EXP); // 还可以选择GL_EXP2或GL_LINEAR 4. 设置雾的密度. glFogf(GL_FOG_DENSITY, 0

opengl纹理操作

我们在前一课中,学习了简单的像素操作,这意味着我们可以使用各种各样的BMP文件来丰富程序的显示效果,于是我们的OpenGL图形程序也不再像以前总是只显示几个多边形那样单调了。——但是这还不够。虽然我们可以将像素数据按照矩形进行缩小和放大,但是还不足以满足我们的要求。例如要将一幅世界地图绘制到一个球体表面,只使用glPixelZoom这样的函数来进行缩放显然是不够的。OpenGL纹理映射功能支持将

OpenGL ES 2.0渲染管线

http://codingnow.cn/opengles/1504.html Opengl es 2.0实现了可编程的图形管线,比起1.x的固定管线要复杂和灵活很多,由两部分规范组成:Opengl es 2.0 API规范和Opengl es着色语言规范。下图是Opengl es 2.0渲染管线,阴影部分是opengl es 2.0的可编程阶段。   1. 顶点着色器(Vert

OpenGL/GLUT实践:流体模拟——数值解法求解Navier-Stokes方程模拟二维流体(电子科技大学信软图形与动画Ⅱ实验)

源码见GitHub:A-UESTCer-s-Code 文章目录 1 实现效果2 实现过程2.1 流体模拟实现2.1.1 网格结构2.1.2 数据结构2.1.3 程序结构1) 更新速度场2) 更新密度值 2.1.4 实现效果 2.2 颜色设置2.2.1 颜色绘制2.2.2 颜色交互2.2.3 实现效果 2.3 障碍设置2.3.1 障碍定义2.3.2 障碍边界条件判定2.3.3 障碍实现2.3.

OpenGL——着色器画一个点

一、 绘制 在窗口中间画一个像素点: #include <GL/glew.h>#include <GLFW/glfw3.h>#include <iostream>using namespace std;#define numVAOs 1GLuint renderingProgram;GLuint vao[numVAOs];GLuintcreateShaderProgram (){c

Unity3D Shader详解:只画顶点或只画线框

在Unity3D开发中,Shader是控制渲染过程的关键组件,它允许开发者自定义物体的渲染方式。有时,为了特定的视觉效果,我们可能需要只渲染模型的顶点或者只显示其线框。下面,我们将详细探讨这两种效果的技术实现,并给出相应的代码示例。 对惹,这里有一个游戏开发交流小组,大家可以点击进来一起交流一下开发经验呀! 只画顶点 在Unity中直接“只画顶点”的概念可能不是非常直观,因为顶点本身只是模型

试用GLFW并创建OpenGL和DX的环境

介绍GLFW GLFW官网:https://www.glfw.org/ GLFW is an Open Source, multi-platform library for OpenGL, OpenGL ES and Vulkan development on the desktop. It provides a simple API for creating windows, contex

图形API学习工程(10):基础光照

工程GIT地址:https://gitee.com/yaksue/yaksue-graphics 目标 在《图形API学习工程(6):创建并使用UniformBuffer》中,UniformBuffer的机制已经配置好,这其实可以让一大批功能得以实现。《图形API学习工程(7):进入3D空间》是其一,其中配置了相机矩阵和投影矩阵,使得能以一个虚拟的“相机”来观察3D世界。本篇的“光照”同样如此