glUniform3f
时间: 2023-11-23 12:07:39 浏览: 31
glUniform3f是OpenGL中的一个函数,它用于设置shader中的uniform变量的值。这个函数用来设置三个浮点数的值,它的函数原型如下:
void glUniform3f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
其中,location参数是要设置的uniform变量的位置,v0、v1、v2是三个浮点数的值。这个函数将会把这三个值设置到指定位置的uniform变量中。
举个例子,如果我们想要设置一个名为color的uniform变量的值为(1.0, 0.5, 0.2),我们可以这样调用glUniform3f函数:
```
GLint loc = glGetUniformLocation(programID, "color");
glUniform3f(loc, 1.0f, 0.5f, 0.2f);
```
这个例子中,我们首先获取了名为color的uniform变量的位置,然后通过glUniform3f函数把值(1.0, 0.5, 0.2)设置到这个变量中。
相关问题
opengl3 画圆球
在OpenGL中,可以通过绘制一组三角形来近似绘制一个圆球。以下是一种实现方法:
1. 首先,定义一个球体的半径r和分割数n(用于控制球体的精度)。
2. 生成球体上每个顶点的坐标。可以使用球面坐标系来计算每个顶点的位置。球面坐标系包括两个角度:θ(纬度)和φ(经度)。对于每个纬度和经度,可以计算出对应的x、y、z坐标,从而生成球体上的所有顶点。
3. 生成球体上每个三角形的顶点索引。可以从球体的顶部(北极)开始,逐层向下生成三角形。每层的三角形数为2n,最后一层只有一个三角形。根据顶点的索引,可以将这些三角形绘制出来。
以下是使用OpenGL3.3绘制圆球的代码:
```c++
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <iostream>
#include <vector>
//定义球体的半径和分割数
float radius = 1.0f;
int segments = 50;
int main()
{
//初始化GLFW
if (!glfwInit())
{
std::cerr << "Failed to initialize GLFW" << std::endl;
return -1;
}
//创建窗口
GLFWwindow* window = glfwCreateWindow(800, 600, "OpenGL Sphere", nullptr, nullptr);
if (!window)
{
std::cerr << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
//将窗口设置为当前上下文
glfwMakeContextCurrent(window);
//初始化GLEW
if (glewInit() != GLEW_OK)
{
std::cerr << "Failed to initialize GLEW" << std::endl;
glfwTerminate();
return -1;
}
//定义球体顶点的坐标和法向量
std::vector<glm::vec3> vertices;
std::vector<glm::vec3> normals;
for (int j = 0; j <= segments; j++)
{
float theta = j * glm::pi<float>() / segments;
float sinTheta = sin(theta);
float cosTheta = cos(theta);
for (int i = 0; i <= segments; i++)
{
float phi = i * 2 * glm::pi<float>() / segments;
float sinPhi = sin(phi);
float cosPhi = cos(phi);
float x = cosPhi * sinTheta;
float y = cosTheta;
float z = sinPhi * sinTheta;
vertices.push_back(glm::vec3(x, y, z) * radius);
normals.push_back(glm::vec3(x, y, z));
}
}
//定义球体顶点的索引
std::vector<unsigned int> indices;
for (int j = 0; j < segments; j++)
{
for (int i = 0; i < segments; i++)
{
unsigned int index1 = j * (segments + 1) + i;
unsigned int index2 = j * (segments + 1) + i + 1;
unsigned int index3 = (j + 1) * (segments + 1) + i;
unsigned int index4 = (j + 1) * (segments + 1) + i + 1;
indices.push_back(index1);
indices.push_back(index3);
indices.push_back(index2);
indices.push_back(index2);
indices.push_back(index3);
indices.push_back(index4);
}
}
//创建VBO和VAO
GLuint vbo, vao, ebo;
glGenBuffers(1, &vbo);
glGenVertexArrays(1, &vao);
glGenBuffers(1, &ebo);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(glm::vec3), vertices.data(), GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), indices.data(), GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(glm::vec3), (void*)0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(glm::vec3), (void*)0);
//创建着色器程序
GLuint shaderProgram = glCreateProgram();
//编译顶点着色器
const char* vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"layout (location = 1) in vec3 aNormal;\n"
"out vec3 Normal;\n"
"out vec3 FragPos;\n"
"uniform mat4 model;\n"
"uniform mat4 view;\n"
"uniform mat4 projection;\n"
"void main()\n"
"{\n"
" gl_Position = projection * view * model * vec4(aPos, 1.0);\n"
" Normal = mat3(transpose(inverse(model))) * aNormal;\n"
" FragPos = vec3(model * vec4(aPos, 1.0));\n"
"}\0";
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, nullptr);
glCompileShader(vertexShader);
//检查顶点着色器是否编译成功
int success;
char infoLog[512];
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vertexShader, 512, nullptr, infoLog);
std::cerr << "Failed to compile vertex shader: " << infoLog << std::endl;
return -1;
}
//编译片段着色器
const char* fragmentShaderSource = "#version 330 core\n"
"in vec3 Normal;\n"
"in vec3 FragPos;\n"
"out vec4 FragColor;\n"
"uniform vec3 lightPos;\n"
"uniform vec3 viewPos;\n"
"uniform vec3 objectColor;\n"
"uniform vec3 lightColor;\n"
"void main()\n"
"{\n"
" vec3 ambient = 0.2 * lightColor;\n"
" vec3 norm = normalize(Normal);\n"
" vec3 lightDir = normalize(lightPos - FragPos);\n"
" float diff = max(dot(norm, lightDir), 0.0);\n"
" vec3 diffuse = diff * lightColor;\n"
" vec3 viewDir = normalize(viewPos - FragPos);\n"
" vec3 reflectDir = reflect(-lightDir, norm);\n"
" float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32);\n"
" vec3 specular = spec * lightColor;\n"
" vec3 result = (ambient + diffuse + specular) * objectColor;\n"
" FragColor = vec4(result, 1.0);\n"
"}\0";
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, nullptr);
glCompileShader(fragmentShader);
//检查片段着色器是否编译成功
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(fragmentShader, 512, nullptr, infoLog);
std::cerr << "Failed to compile fragment shader: " << infoLog << std::endl;
return -1;
}
//将着色器链接到着色器程序中
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
//检查着色器程序是否链接成功
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
if (!success)
{
glGetProgramInfoLog(shaderProgram, 512, nullptr, infoLog);
std::cerr << "Failed to link shader program: " << infoLog << std::endl;
return -1;
}
//删除着色器对象
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
//设置光源和视点位置
glm::vec3 lightPos(0.0f, 1.0f, 0.0f);
glm::vec3 viewPos(0.0f, 0.0f, 3.0f);
//启用深度测试
glEnable(GL_DEPTH_TEST);
//设置清除颜色和深度缓冲的值
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//设置模型矩阵、视图矩阵和投影矩阵
glm::mat4 model = glm::mat4(1.0f);
glm::mat4 view = glm::lookAt(viewPos, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
glm::mat4 projection = glm::perspective(glm::radians(45.0f), 800.0f / 600.0f, 0.1f, 100.0f);
//设置着色器程序中的uniform变量
glUseProgram(shaderProgram);
glUniform3fv(glGetUniformLocation(shaderProgram, "lightPos"), 1, glm::value_ptr(lightPos));
glUniform3fv(glGetUniformLocation(shaderProgram, "viewPos"), 1, glm::value_ptr(viewPos));
glUniform3fv(glGetUniformLocation(shaderProgram, "objectColor"), 1, glm::value_ptr(glm::vec3(1.0f, 0.5f, 0.31f)));
glUniform3fv(glGetUniformLocation(shaderProgram, "lightColor"), 1, glm::value_ptr(glm::vec3(1.0f, 1.0f, 1.0f)));
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "model"), 1, GL_FALSE, glm::value_ptr(model));
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "view"), 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
//绘制球体
glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);
//交换缓冲区并查询事件
glfwSwapBuffers(window);
glfwPollEvents();
//释放资源
glDeleteProgram(shaderProgram);
glDeleteBuffers(1, &vbo);
glDeleteVertexArrays(1, &vao);
glDeleteBuffers(1, &ebo);
//终止GLFW
glfwTerminate();
return 0;
}
```
该代码中使用了glm库来进行矩阵和向量的计算。顶点着色器主要负责将模型空间中的顶点坐标转换为剪裁空间中的坐标,并计算出每个顶点的法向量。片段着色器主要负责计算每个片段的颜色,包括环境光、漫反射和镜面反射。在主函数中,首先生成球体的顶点坐标和法向量,然后使用VBO和VAO来存储和绑定这些数据。接着创建着色器程序,并将uniform变量的值传递给着色器。最后,使用glDrawElements函数来绘制球体。
void renderFrame(int w, int h, unsigned char* image, const char* my2String,Rect rect) { glClear(GL_COLOR_BUFFER_BIT); // glBindFramebuffer(GL_FRAMEBUFFER, gTexture); glUseProgram(gProgram); glBindFramebuffer(GL_FRAMEBUFFER, gFbo); u_MosaicPosition = glGetUniformLocation(gProgram, "uMosaicPosition"); glUniform2f(u_MosaicPosition, rect.x, rect.y); u_MosaicSize = glGetUniformLocation(gProgram, "uMosaicSize"); glUniform1f(u_MosaicSize, rect.width); texture_uniform = glGetUniformLocation(gProgram, "Texture"); glUniform1i(texture_uniform, 0); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, indices); glPixelStorei(GL_PACK_ALIGNMENT, 1); glReadPixels(0, 0, w, h, GL_RGB, GL_UNSIGNED_BYTE, image); //saveRGB(my2String, image, w, h); //eglSwapBuffers(eglGetCurrentDisplay(), eglGetCurrentSurface(EGL_DRAW)); }每行都是什么意思
这是一个渲染图像的函数,下面是每行代码的含义:
1. 清空颜色缓冲区
```
glClear(GL_COLOR_BUFFER_BIT);
```
2. 使用着色器程序
```
glUseProgram(gProgram);
```
3. 绑定帧缓冲对象
```
glBindFramebuffer(GL_FRAMEBUFFER, gFbo);
```
4. 获取着色器程序中的uniform变量uMosaicPosition的位置,并将矩形的左下角位置传递给它
```
u_MosaicPosition = glGetUniformLocation(gProgram, "uMosaicPosition");
glUniform2f(u_MosaicPosition, rect.x, rect.y);
```
5. 获取着色器程序中的uniform变量uMosaicSize的位置,并将矩形的宽度传递给它
```
u_MosaicSize = glGetUniformLocation(gProgram, "uMosaicSize");
glUniform1f(u_MosaicSize, rect.width);
```
6. 获取着色器程序中的uniform变量Texture的位置,并将纹理单元编号传递给它
```
texture_uniform = glGetUniformLocation(gProgram, "Texture");
glUniform1i(texture_uniform, 0);
```
7. 绘制矩形,使用索引缓冲区进行绘制
```
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, indices);
```
8. 读取像素数据到内存中的image数组中
```
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glReadPixels(0, 0, w, h, GL_RGB, GL_UNSIGNED_BYTE, image);
```
9. 保存图像到文件(这行代码被注释掉了)
```
//saveRGB(my2String, image, w, h);
```
10. 交换缓冲区(这行代码被注释掉了)
```
//eglSwapBuffers(eglGetCurrentDisplay(), eglGetCurrentSurface(EGL_DRAW));
```