opengl 学习 之 11 lesson
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的更多相关文章
- OpenGL学习进程(11)第八课:颜色绘制的详解
本节是OpenGL学习的第八个课时,下面将详细介绍OpenGL的颜色模式,颜色混合以及抗锯齿. (1)颜色模式: OpenGL支持两种颜色模式:一种是RGBA,一种是颜色索引模式. R ...
- OpenGL学习之路(一)
1 引子 虽然是计算机科班出身,但从小对几何方面的东西就不太感冒,空间想象能力也较差,所以从本科到研究生,基本没接触过<计算机图形学>.为什么说基本没学过呢?因为好奇(尤其是惊叹于三维游戏 ...
- OpenGL学习之路(三)
1 引子 这些天公司一次次的软件发布节点忙的博主不可开交,另外还有其它的一些事也占用了很多时间.现在坐在电脑前,在很安静的环境下,与大家分享自己的OpenGL学习笔记和理解心得,感到格外舒服.这让我回 ...
- OpenGL学习之路(四)
1 引子 上次读书笔记主要是学习了应用三维坐标变换矩阵对二维的图形进行变换,并附带介绍了GLSL语言的编译.链接相关的知识,之后介绍了GLSL中变量的修饰符,着重介绍了uniform修饰符,来向着色器 ...
- OpenGL学习之windows下安装opengl的glut库
OpenGL学习之windows下安装opengl的glut库 GLUT不是OpenGL所必须的,但它会给我们的学习带来一定的方便,推荐安装. Windows环境下的GLUT下载地址:(大小约为15 ...
- OpenGL学习进程(7)第五课:点、边和图形(二)边
本节是OpenGL学习的第五个课时,下面介绍OpenGL边的相关知识: (1)边的概念: 数学上的直线没有宽度,但OpenGL的直线则是有宽度的.同时,OpenGL的直线必须是有限长度,而不是像数学概 ...
- OpenGL学习进程(4)第二课:绘制图形
本节是OpenGL学习的第二个课时,下面介绍如何用点和线来绘制图形: (1)用点的坐标来绘制矩形: #include <GL/glut.h> void display(void) ...
- OpenGL学习进程(3)第一课:初始化窗体
本节是OpenGL学习的第一个课时,下面介绍如何初始化一个窗体: (1)显示一个有蓝色背景的窗体: #include <GL/glut.h> #include <st ...
- OpenGL学习笔记3——缓冲区对象
在GL中特别提出了缓冲区对象这一概念,是针对提高绘图效率的一个手段.由于GL的架构是基于客户——服务器模型建立的,因此默认所有的绘图数据均是存储在本地客户端,通过GL内核渲染处理以后再将数据发往GPU ...
- OpenGL学习进程(12)第九课:矩阵乘法实现3D变换
本节是OpenGL学习的第九个课时,下面将详细介绍OpenGL的多种3D变换和如何操作矩阵堆栈. (1)3D变换: OpenGL中绘制3D世界的空间变换包括:模型变换.视图变换.投影变换和视口 ...
随机推荐
- 备份一个有的时候,可能需要把其它exe或者dll包含在主程序中....
1.选中附件,右键生成操作选择 嵌入的资源,例如:handle.exe 2.FileUtil 1 using System.IO; 2 using System.Reflection; 3 4 na ...
- 指向const的指针和const指针的区别
1. 指向常量的指针(指向const的指针) 指向const的指针,不能改变其所指变量(对象)的值,或者说不能通过这个指向const的指针去改变所指的变量(对象)的值 // 指向const的指针,不能 ...
- 开源的DeekWiki加入MCP,为您的Cursor提供开源项目分析,轻松让AI掌握开源项目使用文档!
OpenDeekWiki加入MCP,为您的Cursor提供开源项目分析,轻松让AI掌握开源项目使用文档! OpenDeepWiki 是参考DeepWiki 作为灵感,基于 .NET 9 和 Seman ...
- 卷积神经网络 CNN BP算法推导
重点在对CNN的理解后, 理解对卷积层的的 梯度(导数) 推演. 回顾 CNN 首先是对神经网络, 前向, 后向的基本认识. 神经网络初步认识来看, 跟传统的 ML 理论的区别在于, 它更像一个经验的 ...
- 网络编程:select
原理:参考:https://my.oschina.net/fileoptions/blog/911091 select中内核函数有哪些 源码实现: #undef __NFDBITS #define _ ...
- argparse基本功能极简介绍
argparse基本功能极简介绍 python脚本文件可以通过命令行的方式调用,在这种调用方法中,可以通过sys.argv来把命令行参数传入脚本文件,通过这种方式传入的参数是string,并且需要将该 ...
- ssh免密登录设置 (普通用户和root用户)
普通用户如何设置免密码ssh到另一台服务器 一.场景描述: 我有A,B两台服务器,需要实现让A服务器的普通用户(ftpuser)不用输入密码就可以连接到B的(ftpuser)(此处A,B服务器的账户可 ...
- Fiddler抓包工具安装HTTPS证书
安装好之后,打开Fiddler根目录,打开CMD 执行以下内容 makecert.exe -r -ss my -n "CN=DO_NOT_TRUST_FiddlerRoot, O=DO_NO ...
- 团队如何限制合适的在制品(WIP)数量
看板之父David Anderson曾说过" 看板的本质是一个很朴素的思想:在制品必须被限制."但对于团队来说,确定一个合适的在制品限制可能是件棘手的事. 在 <看板快速启动 ...
- Kubernetes控制器-ReplicaSet
Kubernetes控制器-ReplicaSet 控制循环 Kubernetes控制器会监听资源的创建.更新.删除事件,并触发Reconcile函数作为响应.整个调整过程被称作Reconclile L ...