opengl 学习 之 11 lesson

简介

2D纹理。简单来说就是用一个四边形的小框框,UV映射图片。

这里用了多个shader,一个是关于模型的,一个是关于图片的。

link

http://www.opengl-tutorial.org/uncategorized/2017/06/07/website-update/

步骤

bind the buffers, fifill them, select the shader program, bind the texture, enable/bind/confifigure the vertex attributes, enable the blending, and call glDrawArrays.

code

// Include standard headers
#include <stdio.h>
#include <stdlib.h>
#include <vector> // Include GLEW
#include <GL/glew.h> // Include GLFW
#include <GLFW/glfw3.h>
GLFWwindow* window; // Include GLM
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
using namespace glm; #include <common/shader.hpp>
#include <common/texture.hpp>
#include <common/controls.hpp>
#include <common/objloader.hpp>
#include <common/vboindexer.hpp>
#include <common/text2D.hpp> int main( void )
{
// Initialise GLFW
if( !glfwInit() )
{
fprintf( stderr, "Failed to initialize GLFW\n" );
getchar();
return -1;
} glfwWindowHint(GLFW_SAMPLES, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // To make MacOS happy; should not be needed
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // Open a window and create its OpenGL context
window = glfwCreateWindow( 1024, 768, "Tutorial 11 - 2D Fonts", NULL, NULL);
if( window == NULL ){
fprintf( stderr, "Failed to open GLFW window. If you have an Intel GPU, they are not 3.3 compatible. Try the 2.1 version of the tutorials.\n" );
getchar();
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window); // Initialize GLEW
glewExperimental = true; // Needed for core profile
if (glewInit() != GLEW_OK) {
fprintf(stderr, "Failed to initialize GLEW\n");
getchar();
glfwTerminate();
return -1;
} // Ensure we can capture the escape key being pressed below
glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
// Hide the mouse and enable unlimited mouvement
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); // Set the mouse at the center of the screen
glfwPollEvents();
glfwSetCursorPos(window, 1024/2, 768/2); // Dark blue background
glClearColor(0.0f, 0.0f, 0.4f, 0.0f); // Enable depth test
glEnable(GL_DEPTH_TEST);
// Accept fragment if it closer to the camera than the former one
glDepthFunc(GL_LESS); // Cull triangles which normal is not towards the camera
glEnable(GL_CULL_FACE); GLuint VertexArrayID;
glGenVertexArrays(1, &VertexArrayID);
glBindVertexArray(VertexArrayID); // Create and compile our GLSL program from the shaders
GLuint programID = LoadShaders( "StandardShading.vertexshader", "StandardShading.fragmentshader" ); // Get a handle for our "MVP" uniform
GLuint MatrixID = glGetUniformLocation(programID, "MVP");
GLuint ViewMatrixID = glGetUniformLocation(programID, "V");
GLuint ModelMatrixID = glGetUniformLocation(programID, "M"); // Load the texture
GLuint Texture = loadDDS("uvmap.DDS"); // Get a handle for our "myTextureSampler" uniform
GLuint TextureID = glGetUniformLocation(programID, "myTextureSampler"); // Read our .obj file
std::vector<glm::vec3> vertices;
std::vector<glm::vec2> uvs;
std::vector<glm::vec3> normals;
bool res = loadOBJ("suzanne.obj", vertices, uvs, normals); std::vector<unsigned short> indices;
std::vector<glm::vec3> indexed_vertices;
std::vector<glm::vec2> indexed_uvs;
std::vector<glm::vec3> indexed_normals;
indexVBO(vertices, uvs, normals, indices, indexed_vertices, indexed_uvs, indexed_normals); // Load it into a VBO GLuint vertexbuffer;
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, indexed_vertices.size() * sizeof(glm::vec3), &indexed_vertices[0], GL_STATIC_DRAW); GLuint uvbuffer;
glGenBuffers(1, &uvbuffer);
glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
glBufferData(GL_ARRAY_BUFFER, indexed_uvs.size() * sizeof(glm::vec2), &indexed_uvs[0], GL_STATIC_DRAW); GLuint normalbuffer;
glGenBuffers(1, &normalbuffer);
glBindBuffer(GL_ARRAY_BUFFER, normalbuffer);
glBufferData(GL_ARRAY_BUFFER, indexed_normals.size() * sizeof(glm::vec3), &indexed_normals[0], GL_STATIC_DRAW); // Generate a buffer for the indices as well
GLuint elementbuffer;
glGenBuffers(1, &elementbuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned short), &indices[0], GL_STATIC_DRAW); // Get a handle for our "LightPosition" uniform
glUseProgram(programID);
GLuint LightID = glGetUniformLocation(programID, "LightPosition_worldspace"); // Initialize our little text library with the Holstein font
initText2D( "Holstein.DDS" ); // For speed computation
double lastTime = glfwGetTime();
int nbFrames = 0; do{ // Measure speed
double currentTime = glfwGetTime();
nbFrames++;
if ( currentTime - lastTime >= 1.0 ){ // If last prinf() was more than 1sec ago
// printf and reset
printf("%f ms/frame\n", 1000.0/double(nbFrames));
nbFrames = 0;
lastTime += 1.0;
} // Clear the screen
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Use our shader
glUseProgram(programID); // Compute the MVP matrix from keyboard and mouse input
computeMatricesFromInputs();
glm::mat4 ProjectionMatrix = getProjectionMatrix();
glm::mat4 ViewMatrix = getViewMatrix();
glm::mat4 ModelMatrix = glm::mat4(1.0);
glm::mat4 MVP = ProjectionMatrix * ViewMatrix * ModelMatrix; // Send our transformation to the currently bound shader,
// in the "MVP" uniform
glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
glUniformMatrix4fv(ModelMatrixID, 1, GL_FALSE, &ModelMatrix[0][0]);
glUniformMatrix4fv(ViewMatrixID, 1, GL_FALSE, &ViewMatrix[0][0]); glm::vec3 lightPos = glm::vec3(4,4,4);
glUniform3f(LightID, lightPos.x, lightPos.y, lightPos.z); // Bind our texture in Texture Unit 0
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, Texture);
// Set our "myTextureSampler" sampler to use Texture Unit 0
glUniform1i(TextureID, 0); // 1rst attribute buffer : vertices
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(
0, // attribute
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
); // 2nd attribute buffer : UVs
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
glVertexAttribPointer(
1, // attribute
2, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
); // 3rd attribute buffer : normals
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, normalbuffer);
glVertexAttribPointer(
2, // attribute
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
); // Index buffer
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer); // Draw the triangles !
glDrawElements(
GL_TRIANGLES, // mode
indices.size(), // count
GL_UNSIGNED_SHORT, // type
(void*)0 // element array buffer offset
); glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2); char text[256];
sprintf(text,"%.2f sec", glfwGetTime() );
printText2D(text, 10, 500, 60); // Swap buffers
glfwSwapBuffers(window);
glfwPollEvents(); } // Check if the ESC key was pressed or the window was closed
while( glfwGetKey(window, GLFW_KEY_ESCAPE ) != GLFW_PRESS &&
glfwWindowShouldClose(window) == 0 ); // Cleanup VBO, shader and texture
glDeleteBuffers(1, &vertexbuffer);
glDeleteBuffers(1, &uvbuffer);
glDeleteBuffers(1, &normalbuffer);
glDeleteBuffers(1, &elementbuffer);
glDeleteProgram(programID);
glDeleteTextures(1, &Texture);
glDeleteVertexArrays(1, &VertexArrayID); // Delete the text's VBO, the shader and the texture
cleanupText2D(); // Close OpenGL window and terminate GLFW
glfwTerminate(); return 0;
}
#ifndef TEXT2D_HPP
#define TEXT2D_HPP void initText2D(const char * texturePath);
void printText2D(const char * text, int x, int y, int size);
void cleanupText2D(); #endif

#include <vector>
#include <cstring> #include <GL/glew.h> #include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
using namespace glm; #include "shader.hpp"
#include "texture.hpp" #include "text2D.hpp" unsigned int Text2DTextureID;
unsigned int Text2DVertexBufferID;
unsigned int Text2DUVBufferID;
unsigned int Text2DShaderID;
unsigned int Text2DUniformID; void initText2D(const char * texturePath){ // Initialize texture
Text2DTextureID = loadDDS(texturePath); // Initialize VBO
glGenBuffers(1, &Text2DVertexBufferID);
glGenBuffers(1, &Text2DUVBufferID); // Initialize Shader
Text2DShaderID = LoadShaders( "TextVertexShader.vertexshader", "TextVertexShader.fragmentshader" ); // Initialize uniforms' IDs
Text2DUniformID = glGetUniformLocation( Text2DShaderID, "myTextureSampler" ); } void printText2D(const char * text, int x, int y, int size){ unsigned int length = strlen(text); // Fill buffers
std::vector<glm::vec2> vertices;
std::vector<glm::vec2> UVs;
for ( unsigned int i=0 ; i<length ; i++ ){ glm::vec2 vertex_up_left = glm::vec2( x+i*size , y+size );
glm::vec2 vertex_up_right = glm::vec2( x+i*size+size, y+size );
glm::vec2 vertex_down_right = glm::vec2( x+i*size+size, y );
glm::vec2 vertex_down_left = glm::vec2( x+i*size , y ); vertices.push_back(vertex_up_left );
vertices.push_back(vertex_down_left );
vertices.push_back(vertex_up_right ); vertices.push_back(vertex_down_right);
vertices.push_back(vertex_up_right);
vertices.push_back(vertex_down_left); char character = text[i];
float uv_x = (character%16)/16.0f;
float uv_y = (character/16)/16.0f; glm::vec2 uv_up_left = glm::vec2( uv_x , uv_y );
glm::vec2 uv_up_right = glm::vec2( uv_x+1.0f/16.0f, uv_y );
glm::vec2 uv_down_right = glm::vec2( uv_x+1.0f/16.0f, (uv_y + 1.0f/16.0f) );
glm::vec2 uv_down_left = glm::vec2( uv_x , (uv_y + 1.0f/16.0f) );
UVs.push_back(uv_up_left );
UVs.push_back(uv_down_left );
UVs.push_back(uv_up_right ); UVs.push_back(uv_down_right);
UVs.push_back(uv_up_right);
UVs.push_back(uv_down_left);
}
glBindBuffer(GL_ARRAY_BUFFER, Text2DVertexBufferID);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(glm::vec2), &vertices[0], GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, Text2DUVBufferID);
glBufferData(GL_ARRAY_BUFFER, UVs.size() * sizeof(glm::vec2), &UVs[0], GL_STATIC_DRAW); // Bind shader
glUseProgram(Text2DShaderID); // Bind texture
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, Text2DTextureID);
// Set our "myTextureSampler" sampler to use Texture Unit 0
glUniform1i(Text2DUniformID, 0); // 1rst attribute buffer : vertices
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, Text2DVertexBufferID);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)0 ); // 2nd attribute buffer : UVs
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, Text2DUVBufferID);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void*)0 ); glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // Draw call
glDrawArrays(GL_TRIANGLES, 0, vertices.size() ); glDisable(GL_BLEND); glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1); } void cleanupText2D(){ // Delete buffers
glDeleteBuffers(1, &Text2DVertexBufferID);
glDeleteBuffers(1, &Text2DUVBufferID); // Delete texture
glDeleteTextures(1, &Text2DTextureID); // Delete shader
glDeleteProgram(Text2DShaderID);
}
#version 330 core

// Input vertex data, different for all executions of this shader.
layout(location = 0) in vec2 vertexPosition_screenspace;
layout(location = 1) in vec2 vertexUV; // Output data ; will be interpolated for each fragment.
out vec2 UV; void main(){ // Output position of the vertex, in clip space
// map [0..800][0..600] to [-1..1][-1..1]
vec2 vertexPosition_homoneneousspace = vertexPosition_screenspace - vec2(400,300); // [0..800][0..600] -> [-400..400][-300..300]
vertexPosition_homoneneousspace /= vec2(400,300);
gl_Position = vec4(vertexPosition_homoneneousspace,0,1); // UV of the vertex. No special space for this one.
UV = vertexUV;
}
#version 330 core

// Interpolated values from the vertex shaders
in vec2 UV; // Ouput data
out vec4 color; // Values that stay constant for the whole mesh.
uniform sampler2D myTextureSampler; void main(){ color = texture( myTextureSampler, UV ); }

opengl 学习 之 11 lesson的更多相关文章

  1. OpenGL学习进程(11)第八课:颜色绘制的详解

        本节是OpenGL学习的第八个课时,下面将详细介绍OpenGL的颜色模式,颜色混合以及抗锯齿.     (1)颜色模式: OpenGL支持两种颜色模式:一种是RGBA,一种是颜色索引模式. R ...

  2. OpenGL学习之路(一)

    1 引子 虽然是计算机科班出身,但从小对几何方面的东西就不太感冒,空间想象能力也较差,所以从本科到研究生,基本没接触过<计算机图形学>.为什么说基本没学过呢?因为好奇(尤其是惊叹于三维游戏 ...

  3. OpenGL学习之路(三)

    1 引子 这些天公司一次次的软件发布节点忙的博主不可开交,另外还有其它的一些事也占用了很多时间.现在坐在电脑前,在很安静的环境下,与大家分享自己的OpenGL学习笔记和理解心得,感到格外舒服.这让我回 ...

  4. OpenGL学习之路(四)

    1 引子 上次读书笔记主要是学习了应用三维坐标变换矩阵对二维的图形进行变换,并附带介绍了GLSL语言的编译.链接相关的知识,之后介绍了GLSL中变量的修饰符,着重介绍了uniform修饰符,来向着色器 ...

  5. OpenGL学习之windows下安装opengl的glut库

    OpenGL学习之windows下安装opengl的glut库 GLUT不是OpenGL所必须的,但它会给我们的学习带来一定的方便,推荐安装.  Windows环境下的GLUT下载地址:(大小约为15 ...

  6. OpenGL学习进程(7)第五课:点、边和图形(二)边

    本节是OpenGL学习的第五个课时,下面介绍OpenGL边的相关知识: (1)边的概念: 数学上的直线没有宽度,但OpenGL的直线则是有宽度的.同时,OpenGL的直线必须是有限长度,而不是像数学概 ...

  7. OpenGL学习进程(4)第二课:绘制图形

    本节是OpenGL学习的第二个课时,下面介绍如何用点和线来绘制图形:     (1)用点的坐标来绘制矩形: #include <GL/glut.h> void display(void) ...

  8. OpenGL学习进程(3)第一课:初始化窗体

        本节是OpenGL学习的第一个课时,下面介绍如何初始化一个窗体:     (1)显示一个有蓝色背景的窗体: #include <GL/glut.h> #include <st ...

  9. OpenGL学习笔记3——缓冲区对象

    在GL中特别提出了缓冲区对象这一概念,是针对提高绘图效率的一个手段.由于GL的架构是基于客户——服务器模型建立的,因此默认所有的绘图数据均是存储在本地客户端,通过GL内核渲染处理以后再将数据发往GPU ...

  10. OpenGL学习进程(12)第九课:矩阵乘法实现3D变换

    本节是OpenGL学习的第九个课时,下面将详细介绍OpenGL的多种3D变换和如何操作矩阵堆栈.     (1)3D变换: OpenGL中绘制3D世界的空间变换包括:模型变换.视图变换.投影变换和视口 ...

随机推荐

  1. FastAPI与SQLAlchemy同步数据库集成

    title: FastAPI与SQLAlchemy同步数据库集成 date: 2025/04/15 01:27:37 updated: 2025/04/15 01:27:37 author: cmdr ...

  2. VMware平台的Ubuntu部署完全分布式Hadoop环境

    前言: 此文章是本人初次部署Hadoop的过程记录以及所遇到的问题解决,这篇文章只有实际操作部分,没有理论部分.因本人水平有限,本文难免存在不足的地方,如果您有建议,欢迎留言或私信告知于我,非常感谢. ...

  3. eolinker流程用例步骤之脚本代码[Javascript]:读取多组数据,循环执行同一操作

    特别注意:需要使用全局变量或者预处理前务必阅读本链接https://www.cnblogs.com/becks/p/13713278.html 场景(一)描述: 在未知有多少会员卡的前提下,对会员卡进 ...

  4. 2025dsfz集训Day7: KMP与Trie树

    Day7: KMP与Trie树 \[Designed\ By\ FrankWkd\ -\ Luogu@Lwj54joy,uid=845400 \] 特别感谢 此次课的主讲 - Kwling KMP算法 ...

  5. tar命令打包指定目录及其文件,而不包括其上级目录

    想指定将/var目录下的log目录及其文件打包到当前目录,在压缩包解压时不包括/var目录,可使用如下方式: tar -zcvf log_bak.tar.gz -C /var/ log # 注意log ...

  6. vue3 基础-全局组件和局部组件

    组件和页面的关系可以理解为, 组件是页面的一部分. 形象地理解组件 就和盖房子一样的, 可以将房子粗略拆分3个组件(组成部分) 房顶, 房身, 地基. 同时房顶又可以拆分 ..... 这样在极限的情况 ...

  7. 深入浅出了解生成模型-1:GAN模型原理以及代码实战

    更加好排版:https://www.big-yellow-j.top/posts/2025/05/08/GAN.html 日常使用比较多的生成模型比如GPT/Qwen等这些大多都是"文生文& ...

  8. mybatis下的ResultMap配置一对一以及一对多

    一对一: 在数据库里面有这样的一个主外键关系的表: 我需要查找身份证的号码就要知道这个人的姓名(通过一个SQL语句要查到两个实体类里面的信息): SELECT c.*,p.* FROM idcard ...

  9. 鸿蒙图片、布局元素、信息标记组件Badge

    图片资源存放目录 HarmonyOS鸿蒙的图片存放地址在:entry\src\main\resources\base\media中 我们可以通过:$r('app.media.图片名称') 获取图片 @ ...

  10. 【图书预售】清华大学出版社出版的《JMeter核心技术、性能测试与性能分析》开始预售了

    <JMeter核心技术.性能测试与性能分析>是一本由清华大学出版社出版的图书,JMeter是一款基于Java的压力测试工具,可用于对服务器.网络或对象模拟巨大的负载,在不同压力类别下测试它 ...