opengl光照之漫反射逐顶点渲染与逐像素渲染

来源:互联网 发布:apache beam 实时流 编辑:程序博客网 时间:2024/05/19 23:55

1,逐顶点渲染:模型中有多少个顶点就计算多少次,这种方式比较节约系统资源,但效果比较粗糙

2,逐像素渲染:这种方式计算量特别大,有多少个像素就计算多少次,但是效果会很好

逐顶点渲染漫反射光照效果


顶点shader

attribute vec3 pos;//顶点坐标attribute vec2 texcoord;//纹理坐标attribute vec3 normal;//法线坐标uniform mat4 M;//模型变换矩阵uniform mat4 P;//投影矩阵uniform mat4 V;//摄像机观察矩阵uniform mat4 NM;//normalMatrix   将法线转换到世界坐标系或者视口坐标系的矩阵uniform vec3 U_LightPos;//光源位置  本例只讨论平行光uniform vec4 U_DiffuseLightColor;//漫反射光的颜色uniform vec4 U_DiffuseMaterial;//漫反射光的材质varying vec4 V_DiffuseColor;//最终光照颜色void main(){vec3 L=U_LightPos;//平行光的反射方向  ,方向是由模型上的入射点指向光源,本例所有光线都是平行的//归一化处理L=normalize(L);//将法线转换到世界坐标系或视口坐标系,这步很重要,否则得到的光照是不正确的vec3 n=normalize(mat3(NM)*normal);//得到漫反射光的强度 在 0.0和  L,n的点积之间取最大值  点积就是两向量分量分别相乘然后相加float diffuseIntensity=max(0.0,dot(L,n));//漫反射光的最终计算方式V_DiffuseColor=U_DiffuseLightColor*U_DiffuseMaterial*diffuseIntensity;gl_Position=P*V*M*vec4(pos,1.0);}

这种情况下 fs非常简单

uniform vec4 U_AmbientLightColor;//环境光颜色uniform vec4 U_AmbientMaterial;//环境光材质varying vec4 V_DiffuseColor;void main(){vec4 ambientColor=U_AmbientLightColor*U_AmbientMaterial;gl_FragColor=ambientColor+V_DiffuseColor;//最终渲染像素=环境光+漫反射光}

逐像素渲染漫反射光照效果


将光照计算从顶点shader放到了片段shader

顶点shader

attribute vec3 pos;attribute vec2 texcoord;attribute vec3 normal;uniform mat4 M;uniform mat4 P;uniform mat4 V;uniform mat4 NM;varying vec3 V_Normal; //法线void main(){V_Normal=mat3(NM)*normal;//将法线坐标转换到世界坐标系gl_Position=P*V*M*vec4(pos,1.0);}
片元shader

uniform vec3 U_LightPos;//光源位置uniform vec4 U_AmbientLightColor;//环境光颜色uniform vec4 U_AmbientMaterial;//环境光材质uniform vec4 U_DiffuseLightColor;//漫反射光颜色uniform vec4 U_DiffuseMaterial;//漫反射光材质varying vec3 V_Normal;//顶点shader中已转换到世界坐标系或者视口坐标系的法线,不转换就得不到正确的光照void main(){//计算环境光vec4 ambientColor=U_AmbientLightColor*U_AmbientMaterial;//计算漫反射光//入射光向量vec3 L=U_LightPos;//此次只考虑平行光L=normalize(L);//法线坐标归一化vec3 n=normalize(V_Normal);//计算漫反射光照强度float diffuseIntensity=max(0,dot(L,n));//最终漫反射光照颜色vec4 diffuseColor=U_DiffuseLightColor*U_DiffuseMaterial*diffuseIntensity;//最终渲染像素值gl_FragColor=ambientColor+diffuseColor;}

其中很关键的一点  
uniform mat4 NM;

的计算     也就是normalMatrix的计算方式=模型矩阵的逆矩阵的转置

glm::mat4 modelMatrix = glm::translate<float>(0.0f,0.0f,-3.0f);glm::mat4 projectionMatrix = glm::perspective(50.0f, 800.0f / 600.0f, 0.1f, 1000.0f);//法线矩阵=模型矩阵的逆矩阵的转置glm::mat4 normalMatrix = glm::inverseTranspose(modelMatrix);

完整的渲染函数

#include <windows.h>#include "glew.h"#include <stdio.h>#include <math.h>#include "utils.h"#include "GPUProgram.h"#include "ObjModel.h"#include "FBO.h"#include "FullScreenQuad.h"#include "Glm/glm.hpp"#include "Glm/ext.hpp"#pragma comment(lib,"opengl32.lib")#pragma comment(lib,"glew32.lib")LRESULT CALLBACK GLWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){switch (msg){case WM_CLOSE:PostQuitMessage(0);break;}return DefWindowProc(hwnd,msg,wParam,lParam);}INT WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nShowCmd){WNDCLASSEX wndClass;wndClass.cbClsExtra = 0;wndClass.cbSize = sizeof(WNDCLASSEX);wndClass.cbWndExtra = 0;wndClass.hbrBackground = NULL;wndClass.hCursor = LoadCursor(NULL,IDC_ARROW);wndClass.hIcon = NULL;wndClass.hIconSm = NULL;wndClass.hInstance = hInstance;wndClass.lpfnWndProc=GLWindowProc;wndClass.lpszClassName = L"OpenGL";wndClass.lpszMenuName = NULL;wndClass.style = CS_VREDRAW | CS_HREDRAW;ATOM atom = RegisterClassEx(&wndClass);HWND hwnd = CreateWindowEx(NULL, L"OpenGL", L"RenderWindow", WS_OVERLAPPEDWINDOW, 100, 100, 800, 600, NULL, NULL, hInstance, NULL);HDC dc = GetDC(hwnd);PIXELFORMATDESCRIPTOR pfd;memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));pfd.nVersion = 1;pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_TYPE_RGBA | PFD_DOUBLEBUFFER;pfd.iLayerType = PFD_MAIN_PLANE;pfd.iPixelType = PFD_TYPE_RGBA;pfd.cColorBits = 32;pfd.cDepthBits = 24;pfd.cStencilBits = 8;int pixelFormatID = ChoosePixelFormat(dc, &pfd);SetPixelFormat(dc,pixelFormatID,&pfd);HGLRC rc = wglCreateContext(dc);wglMakeCurrent(dc, rc);glewInit();//初始化环境//加载shader并编译GPUProgram gpuProgram;//逐顶点渲染shader//gpuProgram.AttachShader(GL_VERTEX_SHADER, "Debug/res/shader/diffuse_vs.vs");//gpuProgram.AttachShader(GL_FRAGMENT_SHADER, "Debug/res/shader/diffuse_vs.fs");//逐像素渲染shadergpuProgram.AttachShader(GL_VERTEX_SHADER, "Debug/res/shader/diffuse_fs.vs");gpuProgram.AttachShader(GL_FRAGMENT_SHADER, "Debug/res/shader/diffuse_fs.fs");gpuProgram.Link();//获取shader中变量的引用 并将属性名,产生的引用id放入mapgpuProgram.DetectAttribute("pos");gpuProgram.DetectAttribute("texcoord");gpuProgram.DetectAttribute("normal");gpuProgram.DetectUniform("M");gpuProgram.DetectUniform("V");gpuProgram.DetectUniform("P");gpuProgram.DetectUniform("NM");gpuProgram.DetectUniform("U_AmbientLightColor");gpuProgram.DetectUniform("U_AmbientMaterial");gpuProgram.DetectUniform("U_DiffuseLightColor");gpuProgram.DetectUniform("U_DiffuseMaterial");gpuProgram.DetectUniform("U_LightPos");//加载并解析模型ObjModel model;model.Init("Debug/res/model/Sphere.obj");float identity[] = {1.0f,0,0,0,0,1.0f,0,0,0,0,1.0f,0,0,0,0,1.0f};float ambientLightColor[] = {0.4f,0.4f,0.4f,1.0f};//环境光颜色float ambientMaterial[] = { 0.2f,0.2f,0.2f,1.0f };//环境光材质float diffuseLightColor[] = { 1.0f,1.0f,1.0f,1.0f };//漫反射光颜色float diffuseMaterial[] = { 0.8f,0.8f,0.8f,1.0f };//漫反射光材质float lightPos[] = {1.0f,1.0f,0.0f};glm::mat4 modelMatrix = glm::translate<float>(0.0f,0.0f,-3.0f);glm::mat4 projectionMatrix = glm::perspective(50.0f, 800.0f / 600.0f, 0.1f, 1000.0f);//法线矩阵=模型矩阵的逆矩阵的转置glm::mat4 normalMatrix = glm::inverseTranspose(modelMatrix);glClearColor(41.0f/255.0f,  71.0f/255.0f, 121.0f / 255.0f, 1.0f);ShowWindow(hwnd, SW_SHOW);UpdateWindow(hwnd);MSG msg;while (true){if (PeekMessage(&msg,NULL,NULL,NULL,PM_REMOVE)){if (msg.message==WM_QUIT){break;}TranslateMessage(&msg);DispatchMessage(&msg);}glClearColor(0.0f, 0.0f, 0.0f, 1.0f);glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);glEnable(GL_DEPTH_TEST);glUseProgram(gpuProgram.mProgram);glUniformMatrix4fv(gpuProgram.GetLocation("M"), 1,GL_FALSE, glm::value_ptr(modelMatrix));glUniformMatrix4fv(gpuProgram.GetLocation("V"), 1, GL_FALSE, identity);glUniformMatrix4fv(gpuProgram.GetLocation("P"), 1, GL_FALSE, glm::value_ptr(projectionMatrix));glUniformMatrix4fv(gpuProgram.GetLocation("NM"), 1, GL_FALSE, glm::value_ptr(normalMatrix));glUniform4fv(gpuProgram.GetLocation("U_AmbientLightColor"), 1,ambientLightColor);glUniform4fv(gpuProgram.GetLocation("U_AmbientMaterial"), 1, ambientMaterial);glUniform4fv(gpuProgram.GetLocation("U_DiffuseLightColor"), 1, diffuseLightColor);glUniform4fv(gpuProgram.GetLocation("U_DiffuseMaterial"), 1, diffuseMaterial);glUniform3fv(gpuProgram.GetLocation("U_LightPos"), 1, lightPos);model.Bind(gpuProgram.GetLocation("pos"), gpuProgram.GetLocation("texcoord"), gpuProgram.GetLocation("normal"));model.Draw();glUseProgram(0);glFinish();SwapBuffers(dc);}return 0;}




原创粉丝点击