OpenGL基础22:贴图
在 OpenGL基础13:第一个正方体 中给正方体加了箱子的纹理,但是在后面介绍光照的时候又把纹理属性给丢了,现在尝试在有纹理的基础之上增加光照
一、漫反射贴图
先把之前的纹理加回去
顶点着色器和主代码的处理和之前 OpenGL基础9:纹理 纹理这一章一样,而对于片段着色器,需要进行稍加修改
在 OpenGL基础21:材质 这一章里,给予了物体材质属性,包括:
- ambient:定义了在环境光照下这个物体反射的是什么颜色,通常是和物体颜色相同的颜色
- diffuse:定义了在漫反射光照下物体的颜色,通常是和物体颜色相同的颜色
- specular:设置的是物体受到的镜面光照影响的颜色,或者是反射一个物体特定的镜面高光颜色(暂时不考虑)
- shininess:反光度,值越高,反射光的能力越强,散射得越少,高光点越小(暂时不考虑)
但是,一个物体自身作为一个整体为其拥有一个材质其实是有问题的,例如一辆汽车,轮胎和车窗的材质明显不同,也就是说,对于物体的不同部分,可能会拥有不同的 ambient 和 diffuse 属性
因此,这就需要通过某种方式对每个原始像素独立设置diffuse颜色,这其实就是之前的一直在用的纹理,只不过在这中场景和需求下,我们叫它贴图
用一张图片覆盖住物体,以便我们为每个原始像素索引独立颜色值。在光照场景中,通过纹理来呈现一个物体的diffuse颜色,这个做法被称做漫反射贴图(Diffuse texture)
这样的话,在片段着色器中,原先的 ambient 和 diffuse 属性就要用 diffuse 贴图替代(之所以这两个属性都用 diffuse 是因为大部分情况下,这两者的值是等同的),如下:
#version 330 core
struct Material
{sampler2D diffuse; //贴图vec3 specular; //镜面光色float shininess; //反光度
};
struct Light
{vec3 position;vec3 ambient;vec3 diffuse;vec3 specular;
};
uniform Material material;
uniform Light light;
out vec4 color;
uniform vec3 viewPos;
in vec2 texIn;
in vec3 fragPosIn;
in vec3 normalIn;
void main()
{//环境光vec3 ambient = light.ambient * vec3(texture(material.diffuse, texIn));//漫反射光vec3 norm = normalize(normalIn);vec3 lightDir = normalize(light.position - fragPosIn);float diff = max(dot(norm, lightDir), 0.0f);vec3 diffuse = light.diffuse * (diff * vec3(texture(material.diffuse, texIn)));//镜面光vec3 viewDir = normalize(viewPos - fragPosIn);vec3 reflectDir = reflect(-lightDir, norm);float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);vec3 specular = light.specular * (spec * material.specular);//混合vec3 result = ambient + diffuse + specular;color = vec4(result, 1.0f);
}
好了,效果有了!
如果仔细从各个角度看,会发现一块木箱子居然还会有镜面高光,这不科学,这时可以把 specular 设置为 vec(0.0) 来修正
二、镜面贴图采样
上面的箱子还是非常容易的,因为它有一个特点:每个部分都拥有几乎一致的 diffuse 属性,并且 specular 属性都为 vec(0.0),那么问题来了,假设这个时候我们想要给箱子加一个金属边框要怎么处理?要知道金属拥有较高的反射度,和橡木材质正好相反,如果说只用单独的一个带金属边框的木箱纹理,那肯定也是有问题的,所以这个时候就需要2张纹理贴图:一张为带金属边框的橡木纹理,一张为单纯金属边框纹理
如下,一个 specular 高光的亮度可以通过图片中每个纹理的亮度来获得,可以使用这两张纹理作为漫反射贴图和镜面贴图(来源:https://learnopengl.com/#!Lighting/Lighting-maps)
specular 贴图的每个像素可以显示为一个颜色向量,可以看出,这张纹理中间是一片黑,这也意味着中间部分是露出来的木头材质,在此 specular 属性即对应像素颜色属性正是 vec(0.0)
使用Photoshop或Gimp之类的工具,通过将图片进行裁剪,将某部分调整成黑白图样,并调整亮度/对比度的做法,可以非常容易将一个diffuse纹理贴图处理为specular贴图,这样的贴图最好为黑白
有了上面的经验,就知道怎么修改代码逻辑了:
#version 330 core
struct Material
{sampler2D diffuse; //贴图sampler2D specular; //镜面贴图float shininess; //反光度
};
struct Light
{vec3 position;vec3 ambient;vec3 diffuse;vec3 specular;
};
uniform Material material;
uniform Light light;
out vec4 color;
uniform vec3 viewPos;
in vec2 texIn;
in vec3 fragPosIn;
in vec3 normalIn;
void main()
{//环境光vec3 ambient = light.ambient * vec3(texture(material.diffuse, texIn));//漫反射光vec3 norm = normalize(normalIn);vec3 lightDir = normalize(light.position - fragPosIn);float diff = max(dot(norm, lightDir), 0.0f);vec3 diffuse = light.diffuse * (diff * vec3(texture(material.diffuse, texIn)));//镜面光vec3 viewDir = normalize(viewPos - fragPosIn);vec3 reflectDir = reflect(-lightDir, norm);float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);vec3 specular = light.specular * (spec * vec3(texture(material.specular, texIn)));//混合vec3 result = ambient + diffuse + specular;color = vec4(result, 1.0f);
}
效果如下:
三、放射光贴图
上面使用了漫反射贴图和镜面贴图,物体已经有点真实的感觉了,后面还有法线贴图和反射贴图,可以给物体更完美的细节,只是这里就暂时不讲了
这里可以再提一个非常简单的贴图:放射光贴图,先上整篇文章的完整代码和效果,非常容易
#version 330 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 normal;
layout (location = 2) in vec2 texture;
out vec2 texIn;
out vec3 normalIn;
out vec3 fragPosIn;
uniform mat4 model; //模型矩阵
uniform mat4 view; //观察矩阵
uniform mat4 projection; //投影矩阵
void main()
{gl_Position = projection * view * model * vec4(position, 1.0);texIn = vec2(texture.x, 1.0f - texture.y);fragPosIn = vec3(model * vec4(position, 1.0f));normalIn = mat3(transpose(inverse(model))) * normal;
}//#version 330 core
struct Material
{sampler2D diffuse; //贴图sampler2D specular; //镜面贴图sampler2D emission; //放射贴图float shininess; //反光度
};
struct Light
{vec3 position;vec3 ambient;vec3 diffuse;vec3 specular;
};
uniform Material material;
uniform Light light;
out vec4 color;
uniform vec3 viewPos;
in vec2 texIn;
in vec3 fragPosIn;
in vec3 normalIn;
void main()
{//环境光vec3 ambient = light.ambient * vec3(texture(material.diffuse, texIn));//漫反射光vec3 norm = normalize(normalIn);vec3 lightDir = normalize(light.position - fragPosIn);float diff = max(dot(norm, lightDir), 0.0f);vec3 diffuse = light.diffuse * (diff * vec3(texture(material.diffuse, texIn)));//镜面光vec3 viewDir = normalize(viewPos - fragPosIn);vec3 reflectDir = reflect(-lightDir, norm);float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);vec3 specular = light.specular * (spec * vec3(texture(material.specular, texIn)));//放射光贴图vec3 emission = vec3(texture(material.emission, texIn));//混合vec3 result = ambient + diffuse + specular + emission;color = vec4(result, 1.0f);
}
main.cpp:
#include<iostream>
#include<opengl/glew.h>
#define GLEW_STATIC
#include<GLFW/glfw3.h>
#include"Camera.h"
#include<glm/glm.hpp>
#include<glm/gtc/matrix_transform.hpp>
#include<glm/gtc/type_ptr.hpp>
#include"Shader.h"
#include<opengl/freeglut.h>
#include<SOIL.h>bool keys[1024];
Camera camera;
GLfloat lastX, lastY;
bool firstMouse = true;
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
void cameraMove();
glm::vec3 lightPos(1.2f, 1.0f, 2.0f);
const GLuint WIDTH = 800, HEIGHT = 600;int main()
{glfwInit();glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "LearnOpenGL", nullptr, nullptr);glfwMakeContextCurrent(window);glfwSetKeyCallback(window, key_callback);glfwSetCursorPosCallback(window, mouse_callback);glfwSetScrollCallback(window, scroll_callback);glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);glewExperimental = GL_TRUE;glewInit();int width, height;glfwGetFramebufferSize(window, &width, &height);glViewport(0, 0, width, height);Shader shaderObj("ObjVShader.txt", "ObjFShader.txt");Shader shaderLight("LightVShader.txt", "LightFShader.txt");GLfloat vertices[] = {-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f,0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f,0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f,0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f,-0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f,-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f,-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f,0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,-0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f,-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,-0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f,-0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f,-0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f,-0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f,-0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f,-0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f,0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f,0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,-0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f,0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f,0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f,0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f,-0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f,-0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f,-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f,0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f};GLuint VBO, VAO, textureA, textureB, textureC;glGenVertexArrays(1, &VAO);glGenBuffers(1, &VBO);glBindVertexArray(VAO);glBindBuffer(GL_ARRAY_BUFFER, VBO);glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0);glEnableVertexAttribArray(0);glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));glEnableVertexAttribArray(1);glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));glEnableVertexAttribArray(2);int picWidth, picHeight;glGenTextures(1, &textureA);glBindTexture(GL_TEXTURE_2D, textureA);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);unsigned char* image = SOIL_load_image("Texture/wood2.jpg", &picWidth, &picHeight, 0, SOIL_LOAD_RGB);glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, picWidth, picHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, image);glGenerateMipmap(GL_TEXTURE_2D);SOIL_free_image_data(image);glGenTextures(1, &textureB);glBindTexture(GL_TEXTURE_2D, textureB);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST_MIPMAP_NEAREST);image = SOIL_load_image("Texture/specular.jpg", &picWidth, &picHeight, 0, SOIL_LOAD_RGB);glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, picWidth, picHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, image);glGenerateMipmap(GL_TEXTURE_2D);SOIL_free_image_data(image);glGenTextures(1, &textureC);glBindTexture(GL_TEXTURE_2D, textureC);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST_MIPMAP_NEAREST);image = SOIL_load_image("Texture/cloudImg.jpg", &picWidth, &picHeight, 0, SOIL_LOAD_RGB);glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, picWidth, picHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, image);glGenerateMipmap(GL_TEXTURE_2D);SOIL_free_image_data(image);glBindTexture(GL_TEXTURE_2D, 0);shaderObj.Use();glUniform1i(glGetUniformLocation(shaderObj.Program, "material.diffuse"), 0);glUniform1i(glGetUniformLocation(shaderObj.Program, "material.specular"), 1);glUniform1i(glGetUniformLocation(shaderObj.Program, "material.emission"), 2);GLuint lightVAO;glGenVertexArrays(1, &lightVAO);glBindVertexArray(lightVAO);glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0);//VBO数据已经绑定且我们就用之前的顶点数据,所以无需再管理VBOglEnableVertexAttribArray(0);glBindBuffer(GL_ARRAY_BUFFER, 0);glBindVertexArray(0);glEnable(GL_DEPTH_TEST);while (!glfwWindowShouldClose(window)){glfwPollEvents();glClearColor(0.0f, 0.0f, 0.0f, 1.0f);glClear(GL_COLOR_BUFFER_BIT);glClear(GL_DEPTH_BUFFER_BIT);cameraMove();shaderLight.Use();lightPos.x = 1.0f + sin(glfwGetTime()) * 2.0f;lightPos.y = sin(glfwGetTime() / 2.0f) * 1.0f;glm::mat4 view = camera.GetViewMatrix();glm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), (GLfloat)WIDTH / (GLfloat)HEIGHT, 0.1f, 100.0f);glm::mat4 model = glm::translate(glm::mat4(1.0f), lightPos);model = glm::scale(model, glm::vec3(0.2f));GLint modelLoc = glGetUniformLocation(shaderLight.Program, "model");GLint viewLoc = glGetUniformLocation(shaderLight.Program, "view");GLint projLoc = glGetUniformLocation(shaderLight.Program, "projection");glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));glBindVertexArray(lightVAO);glDrawArrays(GL_TRIANGLES, 0, 36);shaderObj.Use();glActiveTexture(GL_TEXTURE0);glBindTexture(GL_TEXTURE_2D, textureA);glActiveTexture(GL_TEXTURE1);glBindTexture(GL_TEXTURE_2D, textureB);glActiveTexture(GL_TEXTURE2);glBindTexture(GL_TEXTURE_2D, textureC);GLint matSpecularLoc = glGetUniformLocation(shaderObj.Program, "material.specular");GLint matShineLoc = glGetUniformLocation(shaderObj.Program, "material.shininess");glUniform3f(matSpecularLoc, 0.0f, 0.0f, 0.0f);glUniform1f(matShineLoc, 32.0f);GLint lightPosLoc = glGetUniformLocation(shaderObj.Program, "light.position");GLint lightAmbientLoc = glGetUniformLocation(shaderObj.Program, "light.ambient");GLint lightDiffuseLoc = glGetUniformLocation(shaderObj.Program, "light.diffuse");GLint lightSpecularLoc = glGetUniformLocation(shaderObj.Program, "light.specular");glUniform3f(lightAmbientLoc, 0.2f, 0.2f, 0.2f);glUniform3f(lightDiffuseLoc, 1.0f, 1.0f, 1.0f);glUniform3f(lightSpecularLoc, 1.0f, 1.0f, 1.0f);glUniform3f(lightPosLoc, lightPos.x, lightPos.y, lightPos.z);GLint viewPosLoc = glGetUniformLocation(shaderObj.Program, "viewPos");glUniform3f(viewPosLoc, camera.Position.x, camera.Position.y, camera.Position.z);model = glm::mat4(1.0f);model = glm::rotate(model, glm::radians(57.0f), glm::vec3(-0.5f, 1.0f, 0.0f));modelLoc = glGetUniformLocation(shaderObj.Program, "model");viewLoc = glGetUniformLocation(shaderObj.Program, "view");projLoc = glGetUniformLocation(shaderObj.Program, "projection");glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));glBindVertexArray(VAO);glDrawArrays(GL_TRIANGLES, 0, 36);glBindVertexArray(0);glfwSwapBuffers(window);}glDeleteVertexArrays(1, &VAO);glDeleteBuffers(1, &VBO);glfwTerminate();return 0;
}GLfloat deltaTime = 0.0f;
GLfloat lastFrame = 0.0f;
void cameraMove()
{GLfloat currentFrame = glfwGetTime();deltaTime = currentFrame - lastFrame;lastFrame = currentFrame;GLfloat cameraSpeed = 1.0f * deltaTime;if (keys[GLFW_KEY_W])camera.ProcessKeyboard(Camera_Movement(FORWARD), deltaTime);if (keys[GLFW_KEY_S])camera.ProcessKeyboard(Camera_Movement(BACKWARD), deltaTime);if (keys[GLFW_KEY_A])camera.ProcessKeyboard(Camera_Movement(LEFT), deltaTime);if (keys[GLFW_KEY_D])camera.ProcessKeyboard(Camera_Movement(RIGHT), deltaTime);
}void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode)
{if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)glfwSetWindowShouldClose(window, GL_TRUE);if (action == GLFW_PRESS) //如果当前是按下操作keys[key] = true;else if (action == GLFW_RELEASE) //松开键盘keys[key] = false;
}void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
{camera.ProcessMouseScroll(yoffset);
}void mouse_callback(GLFWwindow* window, double xpos, double ypos)
{if (firstMouse){lastX = xpos;lastY = ypos;firstMouse = false;}GLfloat xoffset = xpos - lastX;GLfloat yoffset = lastY - ypos;lastX = xpos;lastY = ypos;GLfloat sensitivity = 0.05;xoffset *= sensitivity;yoffset *= sensitivity;camera.ProcessMouseMovement(xoffset, yoffset);
}
可以看到,箱子的每个面上都有被贴上了一块无视光照的“云彩”,这就是放射光贴图,顾名思义,它往往是用来显示物体自身发光(Emit)时可能产生的颜色,例如游戏中宝箱上发光的按钮,楼梯间紧急出口牌子亮的绿光等等
OpenGL基础22:贴图相关推荐
- OpenGL基础49:高度贴图(下)
接上文:OpenGL基础48:高度贴图(上) 四.陡峭视差映射 上文计算纹理偏移的方法是最简单的,但问题也比较大:当你斜视贴图的时候可以看到非常明显的错误 这里有另一种方法,这种方法类似于找连续函数在 ...
- OpenGL基础45:光照矫正(下)之Gamma校正
接上文:OpenGL基础44:光照矫正(上) 四.Gamma矫正 4.1.人的视觉特性 和很多错视图一样,对于下面这张灰阶图,如果1表示纯白,0表示纯黑,那么这张图片的哪个位置代表的是0.5,也就是自 ...
- OpenGL基础23:平行光与点光源
前面几章主要是针对物体,现在开始针对光源! 一.平行光 在 OpenGL基础18:光照基础 这一章里面讲了几种常见光源,先看平行光吧 一个很好的例子就是太阳光,因为离我们的距离过远,所以太阳光的特点就 ...
- OpenGL: 基础篇
本人水平有限,如有问题请以文章形式提出,大家可以讨论吗... [OPENGL怎么用] OPENGL编程类似C编程,实际接口就是C,所以熟悉C是必要的 一般编程可用到的函数库包括: OPENGL实用库: ...
- OpenGL基础知识介绍和简单使用
OpenGL基础知识介绍 OpenGL简介 OpenGL 专业词解析 1.OpenGL上下文[context] 2.渲染 3.顶点数组和顶点缓冲区 4.着色器程序Shader 5.顶点着色器(Vert ...
- opengl基础学习专题 (二) 点直线和多边形
题外话 随着学习的增长,越来越觉得自己很水.关于上一篇博文中推荐用一个 学习opengl的 基于VS2015的 simplec框架.存在 一些问题. 1.这个框架基于VS 的Debug 模式下,没有考 ...
- OpenGL 基础光照ColorsBasic Lighting
OpenGL 基础光照ColorsBasic Lighting 基础光照ColorsBasic Lighting简介 环境光照 漫反射光照 法向量 计算漫反射光照 最后一件事 镜面光照 基础光照Col ...
- [转]OpenGL基础技术讲座--发展历史
OpenGL基础技术讲座--发展历史 第一讲 OpenGL 的发展历史 人们对三维图形技术的研究已经经历了一个很长的历程,而且涌现了许多三维图形开发工具,其中SGI公司推出的GL(Graphics L ...
- [.net 面向对象编程基础] (22) 事件
[.net 面向对象编程基础] (22) 事件 事件(Event)是学习.net面向对象编程很重要的一部分,在学习事件之前,我们实际上已经在很多地方使用了事件,比如控件的click事件等,这些都是. ...
最新文章
- 正则不等于一个字符串_更正一个观念:“积食”不等于“吃多了”
- 锁究竟锁住的是什么?
- EAGER的获取是代码的味道
- 【洛谷 - P1772 】[ZJOI2006]物流运输(dp)
- 程序员,你怎么这么忙?为什么天天熬夜加班?
- 大象喝水(信息学奥赛一本通-T1032)
- 天燃气与电热水器哪个用着成本低?
- java 表格树_00030-layui+java 树形表格treeTable
- Atitit.atiDataStoreService v2 新特性
- VB2010(29)Web部署应用程序
- DH 算法迪菲-赫尔曼算法QUIC协议和HTTP3.0
- Theano入门神经网络(三)
- oracle中if语句用法,Oracle IF语句的使用 | 学步园
- 读书:在别人的盯梢儿和嚼舌根中茁壮成长 | 杂谈
- InsecureProgramming-master——abo4
- u8系统更改了服务器,用友u8服务器地址修改
- Word转图片(使用Spire.doc)
- 经典Bug永流传---每周一“虫”(九)
- android输入法服务,Android调用系统输入法
- pad 锁定屏幕显示方向为竖屏正方向
热门文章
- python表白代码-如何用Python代码向心爱的姑娘花式表白?
- python自动化办公真的好用吗-Python做什么更合适?|老男孩Python自动化运维
- linux系统怎么刷新,Fedora Linux如何更新系统
- oracle配置ipv6_配置 IPv6 接口
- httpclient java 异步_Java的异步HttpClient
- java sort类_JAVA Collections工具类sort()排序方法
- 【动态规划】01背包问题:购物袋
- 【linux】常用网络操作
- 2014——我们都任性过
- 怎么看linux的命令说明,在linux下,怎么用命令来查看版本?