【OpenGL进阶】04.支持多贴图的Shader

2023-11-18

这篇文章来实现一下多贴图的效果。在这篇文章中,再次对代码进行了封装,是代码看起来更加清晰明了:

shader.h中添加了SetTexture接口:

#pragma once
#include "ggl.h"
struct UniformTexture 
{
	GLint mLocation;
	GLuint mTexture;
	UniformTexture()
	{
		mLocation = -1;
		mTexture = 0;
	}
};
class Shader
{
public:
	GLuint mProgram;
	std::map<std::string, UniformTexture*>mUniformTextures;
	GLint mModelMatrixLocation, mViewMatrixLocation, mProjectionMatrixLocation;
	GLint mPositionLocation, mColorLocation, mTexcoordLocation, mNormalLocation;
	void Init(const char* vs, const char* fs);
	void Bind(float* M, float* V, float* P);
	void SetTexture(const char* name, const char* imagePath);
};

shader.cpp:

#include "shader.h"
#include "Utils.h"
#include "vertexbuffer.h"
void Shader::Init(const char* vs, const char* fs)
{
	int nFileSize = 0;
	const char* vsCode = (char*)LoadFileContent(vs, nFileSize);
	const char* fsCode = (char*)LoadFileContent(fs, nFileSize);

	GLuint vsShader = CompileShader(GL_VERTEX_SHADER, vsCode);

	if (vsShader == 0)
	{
		return;
	}
	GLuint fsShader = CompileShader(GL_FRAGMENT_SHADER, fsCode);
	if (fsShader == 0)
	{
		return;
	}
	mProgram = CreateProgram(vsShader, fsShader);
	glDeleteShader(vsShader);
	glDeleteShader(fsShader);

	if (mProgram != 0)
	{
		mModelMatrixLocation = glGetUniformLocation(mProgram, "ModelMatrix");
		mViewMatrixLocation = glGetUniformLocation(mProgram, "ViewMatrix");
		mProjectionMatrixLocation = glGetUniformLocation(mProgram, "ProjectionMatrix");

		mPositionLocation = glGetAttribLocation(mProgram, "position");
		mColorLocation = glGetAttribLocation(mProgram, "color");
		mTexcoordLocation = glGetAttribLocation(mProgram, "texcoord");
		mNormalLocation = glGetAttribLocation(mProgram, "normal");
	}
}

void Shader::Bind(float* M, float* V, float* P)
{
	glUseProgram(mProgram);
	glUniformMatrix4fv(mModelMatrixLocation, 1, GL_FALSE, M);
	glUniformMatrix4fv(mViewMatrixLocation, 1, GL_FALSE, V);
	glUniformMatrix4fv(mProjectionMatrixLocation, 1, GL_FALSE, P);

	int iIndex = 0;
	for (auto iter =mUniformTextures.begin();iter!=mUniformTextures.end();++iter)
	{
		glActiveTexture(GL_TEXTURE0 + iIndex);
		glBindTexture(GL_TEXTURE_2D, iter->second->mTexture);
		glUniform1i(iter->second->mLocation, iIndex++);
	}

	glEnableVertexAttribArray(mPositionLocation);
	glVertexAttribPointer(mPositionLocation, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);
	glEnableVertexAttribArray(mColorLocation);
	glVertexAttribPointer(mColorLocation, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)(sizeof(float) * 4));
	glEnableVertexAttribArray(mTexcoordLocation);
	glVertexAttribPointer(mTexcoordLocation, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)(sizeof(float) * 8));
	glEnableVertexAttribArray(mNormalLocation);
	glVertexAttribPointer(mNormalLocation, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)(sizeof(float) * 12));
}

void Shader::SetTexture(const char* name, const char* imagePath)
{
	auto iter = mUniformTextures.find(name);
	if(iter ==mUniformTextures.end())
	{
		GLint location = glGetUniformLocation(mProgram, name);
		if (location != -1)
		{
			UniformTexture* t = new UniformTexture;
			t->mLocation = location;
			t->mTexture = CreateTexture2DFromBMP(imagePath);
			mUniformTextures.insert(std::pair<std::string, UniformTexture*>(name, t));
		}
		else
		{
			glDeleteTextures(1, &iter->second->mTexture);
			iter->second->mTexture = CreateTexture2DFromBMP(imagePath);
		}
	}
}

vertexbuffer.h中添加了Bind()和UnBind()接口

#pragma once
#include "ggl.h"
struct Vertex
{
	float Position[4];
	float Color[4];
	float Texcoord[4];
	float Normal[4];
};

class VertexBuffer {
public:
	Vertex* mVertexes;
	int mVertexCount;
	GLuint mVBO;
	void SetSize(int vertexCount);
	void SetPosition(int index, float x, float y, float z, float w = 1.0f);
	void SetColor(int index, float r, float g, float b, float a = 1.0f);
	void SetTexcoord(int index, float x, float y);
	void SetNormal(int index, float x, float y, float z);
	void Bind();
	void UnBind();
	Vertex& Get(int index);
};

vertexbuffer.cpp:

#include "vertexbuffer.h"
#include "Utils.h"

void VertexBuffer::SetSize(int vertexCount)
{
	mVertexCount = vertexCount;
	mVertexes = new Vertex[mVertexCount];
	memset(mVertexes, 0, sizeof(Vertex) * mVertexCount);
	mVBO = CreateBufferObject(GL_ARRAY_BUFFER, sizeof(Vertex) * mVertexCount, GL_STATIC_DRAW, nullptr);
}

void VertexBuffer::SetPosition(int index, float x, float y, float z, float w /* = 1.0f */)
{
	mVertexes[index].Position[0] = x;
	mVertexes[index].Position[1] = y;
	mVertexes[index].Position[2] = z;
	mVertexes[index].Position[3] = w;
}

void VertexBuffer::SetColor(int index, float r, float g, float b, float a /* = 1.0f */)
{
	mVertexes[index].Color[0] = r;
	mVertexes[index].Color[1] = g; 
	mVertexes[index].Color[2] = b;
	mVertexes[index].Color[3] = a;
}

void VertexBuffer::SetTexcoord(int index, float x, float y)
{
	mVertexes[index].Texcoord[0] = x;
	mVertexes[index].Texcoord[1] = y;
}

void VertexBuffer::SetNormal(int index, float x, float y, float z)
{
	mVertexes[index].Normal[0] = x;
	mVertexes[index].Normal[1] = y;
	mVertexes[index].Normal[2] = z;
	mVertexes[index].Normal[3] = 1.0;
}

void VertexBuffer::Bind()
{
	glBindBuffer(GL_ARRAY_BUFFER, mVBO);
	glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(Vertex) * mVertexCount, mVertexes);
}

void VertexBuffer::UnBind()
{
	glBindBuffer(GL_ARRAY_BUFFER, 0);
}

Vertex& VertexBuffer::Get(int index)
{
	return mVertexes[index];
}

看下shader的变化

test.vs:

attribute vec4 position;
attribute vec4 color;
attribute vec2 texcoord;
uniform mat4 ModelMatrix;
uniform mat4 ViewMatrix;
uniform mat4 ProjectionMatrix;
varying vec4 V_Color;
varying vec2 V_Texcoord;

void main()
{
    V_Color = color;
    V_Texcoord = texcoord;
    gl_Position = ProjectionMatrix*ViewMatrix*ModelMatrix*position;
}

test.fs:

#ifdef GL_ES
precision mediump float;
#endif
uniform sampler2D U_Texture;
uniform sampler2D U_Texture2;
varying vec4 V_Color;
varying vec2 V_Texcoord;

void main()
{
    gl_FragColor = V_Color*texture2D(U_Texture,V_Texcoord)*texture2D(U_Texture2,V_Texcoord);
}

最后看下Scene.cpp里的调用,代码是不是清爽了许多:

#include "scene.h"
#include "ggl.h"
#include "Utils.h"
#include "ground.h"
#include "shader.h"

GLuint texture;
glm::mat4 modelMatrix, viewMatrix, projectionMatrix;
Ground ground;
Shader* shader;
VertexBuffer* vertexBuffer;

void Init()
{
	vertexBuffer = new VertexBuffer;
	vertexBuffer->SetSize(3);
	vertexBuffer->SetPosition(0, -0.2f, -0.2f, 0.0f);
	vertexBuffer->SetTexcoord(0, 0.0f, 0.0f);
	vertexBuffer->SetColor(0, 1.0f, 1.0f, 1.0f);
	vertexBuffer->SetPosition(1, 0.2f, -0.2f, 0.0f);
	vertexBuffer->SetTexcoord(1, 1.0f, 0.0f);
	vertexBuffer->SetColor(1, 1.0f, 0.0f, 0.0f, 0.0f);
	vertexBuffer->SetPosition(2, 0.0f, 0.2f, 0.0f);
	vertexBuffer->SetTexcoord(2, 0.5f, 1.0f);
	vertexBuffer->SetColor(2, 0.0f, 1.0f, 0.0f);

	shader = new Shader;

	shader->Init("Res/test.vs", "Res/test.fs");
	shader->SetTexture("U_Texture", "Res/test.bmp");
	shader->SetTexture("U_Texture2", "Res/test2.bmp");
	modelMatrix = glm::translate(0.0f, 0.0f, -0.6f);
	ground.Init();
}

void SetViewPortSize(float width, float height)
{
	projectionMatrix = glm::perspective(60.0f, width / height, 0.1f, 1000.0f);
}

void Draw()
{
	float frameTime = GetFrameTime();
	glClearColor(0.1f, 0.4f, 0.6f, 1.0f);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	ground.Draw(viewMatrix, projectionMatrix);
	vertexBuffer->Bind();
	shader->Bind(glm::value_ptr(modelMatrix), glm::value_ptr(viewMatrix), glm::value_ptr(projectionMatrix));
	glDrawArrays(GL_TRIANGLES, 0, 3);
	vertexBuffer->UnBind();
}

看下三角形两个纹理叠加的效果吧:

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【OpenGL进阶】04.支持多贴图的Shader 的相关文章

  • 尝试 glUseProgram 时出现 Opengl 错误 1281

    我有什么想法可以调试这个opengl进一步错误 1281 我正在从文件加载源代码 编译 链接 然后尝试检查错误glUseProgram 在我的对象的绘制方法中 log info gl2 glIsProgram shaderProgram t
  • 从活动顶点数组生成平滑法线

    我正在尝试通过挂钩 OpenGl 调用来破解和修改旧版 opengl 固定管道游戏的多个渲染功能 而我当前的任务是实现着色器照明 我已经创建了一个适当的着色器程序 可以正确照亮大部分对象 但该游戏的地形是在没有提供正常数据的情况下绘制的 游
  • LWJGL 窗口具有透明背景?

    我想创建一个没有 黑色背景 区域的窗口 但您可以看到任何其他打开的窗口等 也就是说 渲染场景并且仅渲染场景 不留框架 不留背景区域 我读过一种方法 该方法涉及渲染到隐藏的 OpenGL 窗口并将其缓冲在内存中 创建透明分层窗口以及从内存复制
  • glGenerateMipmap 是否在 sRGB 纹理的线性空间中执行平均?

    OpenGL 3 3 规范似乎没有要求 mipmap 生成在线性空间中完成 我能找到的只有以下内容 派生的 mipmap 数组的内部格式都与 levelbase 数组和派生数组的维度如下 第 3 8 14 节中描述的要求 的内容 派生数组是
  • 将 CVPixelBuffer 渲染到 NSView (macOS)

    我有一个CVPixelBuffer我正在尝试在屏幕上有效地绘制 转变为低效率的方式NSImage可以工作 但速度非常慢 丢掉了大约 40 的帧数 因此 我尝试使用将其渲染在屏幕上CIContext s drawImage inRect fr
  • 将glm四元数转换为旋转矩阵并与opengl一起使用

    所以我将对象的方向存储在 glm fquat 中 我想用它来旋转我的模型 我怎么做 我试过这个 glPushMatrix glTranslatef position x position y position z glMultMatrixf
  • 对 VBO 中的特定三角形使用不同的纹理

    我有 9 个由三角形组成的四边形 如下所示 我在用着VBO存储有关它们的数据 它们的位置和纹理坐标 我的问题是 是否可以仅使用一个来使四边形 5 具有与其余四边形不同的纹理VBO and shader 绿色代表纹理 1 黄色代表纹理 2 到
  • 使用 openGL、SOIL 加载图像

    我尝试了很多使用 SOIL 在 openGL 中加载和显示图像的示例 运行下面的源代码时 它仅显示一个没有图像的白色四边形 我尝试打开一个名为 foto 的图像 我将图像文件放在程序的文件夹中 bool keyStates new bool
  • 使用 Qt 在 xoverlay 之上绘制

    我希望在使用 Xoverlay 渲染的视频流之上绘制一些 UI 我正在使用 gstreamer 播放视频并使用 xoverlay 在 xvimagesink 上渲染它 我的小部件继承自 QGLWidget 我希望使用 QPainter 绘制
  • 为什么我的 FPS 相机一劳永逸地滚动?

    如果我忽略四元数代数的肮脏细节 我想我理解了旋转和平移变换背后的数学 但仍然不明白我做错了什么 为什么我的相机一劳永逸地滚动 更具体地说 我应该如何从相机的方向 旋转矩阵 计算相机视图矩阵 我正在用 Python 编写一个简约的 3d 引擎
  • 简单的线框格式?

    我正在寻找一种用于线框模型的简单文件格式 我知道 VRML u3D 等 但这些对于我的需求来说似乎很重要 我的标准是 必须有明确的规格 要么是开放的 要么是非常完善 记录的 我只需要 想要 简单的模型 顶点和边 我不想处理面孔或物体 如果格
  • OpenGL 中连续暂停

    void keyPress unsigned char key int x int y int i switch key case f i 3 while i x pos 3 sleep 100 glutPostRedisplay 上面是在
  • 对齐坐标系

    Let s say I have 2 coordinate systems as it is shown in image attached 如何对齐这个坐标系 我知道我需要将第二个坐标系围绕 X 平移 180 度 然后将其平移到第一个坐标
  • 使用 OpenGL 着色器进行数学计算 (C++)

    我有一个矩阵 例如 100x100 尺寸 我需要对每个元素进行计算 matrix i j tt 8 5例如 我有一个巨大的矩阵 我想使用 OpenGL 着色器来实现该算法 我想使用着色器 例如 uniform float val unifo
  • 如何在 GTX 560 及更高版本上使用 OpenGL 进行立体 3D?

    我正在使用在 Windows 7 上运行的开源触觉和 3D 图形库 Chai3D 我重写了该库以使用 Nvidia nvision 执行立体 3D 我将 OpenGL 与 GLUT 一起使用 并使用 glutInitDisplayMode
  • 为什么OpenGL使用float而不是double? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 在 GLUT 中使用鼠标滚轮

    我想在 OpenGL GLUT 程序中使用鼠标滚轮来放大和缩小场景 我怎么做 Freeglut 的 glutMouseWheelFunc 回调与版本相关 并且在 X 中不可靠 使用标准鼠标功能并测试按钮 3 和 4 OpenGlut 对 g
  • OpenGL缓冲区更新[重复]

    这个问题在这里已经有答案了 目前我正在编写一个模拟水的程序 以下是我所做的步骤 创建水面 平面 创建VAO 创建顶点缓冲区对象 在其中存储法线和顶点 将指针绑定到此 VBO 创建索引缓冲区对象 然后我使用 glDrawElements 渲染
  • Opengl 像素完美 2D 绘图

    我正在研究 2d 引擎 它已经工作得很好 但我不断收到像素错误 例如 我的窗口是 960x540 像素 我从 0 0 到 959 0 画一条线 我希望扫描线 0 上的每个像素都会被设置为一种颜色 但事实并非如此 最右边的像素没有被绘制 当我
  • Visual Studio 2010 中的 SOIL 设置

    我无法得到SOIL http www lonesock net soil html正确使用 Visual Studio 2010 我远非 VS 专家 但据我所知 只需执行以下步骤即可使环境正常运行 属性 gt gt C C gt 常规 gt

随机推荐

  • SpringCloud Alibaba应用

    目录 1 服务注册中心 1 1 nacos服务注册与发现 1 1 1 springcloud集成nacos服务注册中心 2 服务配置中心 2 1 nacos服务配置中心 3 远程调用 3 1 openfeign远程调用 4 网关服务 4 1
  • 手把手教你制作Jlink-OB调试器(含原理图、PCB、外壳、固件)

    文章目录 前言 硬件电路 原理图 PCB 焊接调试 待优化和改进的地方 资料下载 历史精选 前言 好久没更新博客和公众号了 感谢大家还没取关哈 好吧 我承认是我太懒了 今天分享一个福利 趁着前段时间嘉立创和捷配打价格战 一天之内 多次降价
  • pycharm 允许并行运行 运行多个文件 运行多个py文件

    pycharm 允许并行运行 运行多个文件 运行多个py文件
  • vue3.x + vite4.3构建属于自己的组件库并发布npm包

    欢迎点击领取 前端面试题进阶指南 前端登顶之巅 最全面的前端知识点梳理总结 分享一个使用比较久的 在国内的项目研发过程中 使用vue框架的项目占比很大 同样延伸出了很多非常优秀的UI组件库 比如element plus ant design
  • GPT自然语言处理模型

    GPT Generative Pre trained Transformer 是一种基于Transformer架构的自然语言处理模型 由OpenAI开发 它是目前最先进的自然语言处理模型之一 可以用于各种任务 例如文本生成 机器翻译 问答系
  • JS+CSS实现一个底部渐变波浪效果

    今天又来分享一个网页特效 自己瞎写的 类似一个波浪效果 并且有背景渐变 就叫做底部渐变波浪把 先看看效果图 实现代码 实现原理也很简单 就是使用 keyframes定义动画函数 然后对每个元素应用animation属性 设置不同的延迟播放时
  • matlab 读取某一文件夹下的文件

    MATLAB 是一个十分强大的科学计算软件 用于各种数据分析和科学计算 在实际工作和研究过程中 我们通常将数据存储在文件中 文件存在于系统的某个目录中 如果需要读取这些文件 可以使用 MATLAB 提供的文件和文件夹操作函数 本文将介绍如何
  • 一、Java基础之一——环境配置

    文章目录 1 1 JavaSE知识体系 1 2 各种语言的应用领域 1 3 Java语言跨平台原理 1 3 1Java语言特点 1 3 2 Java语言跨平台原理 1 3 3 JRE和JDK 1 4 Java环境配置 1 4 1 JDK下载
  • C#——设计一个Windows应用程序,在该程序中定义一个学生类和班级类

    设计一个Windows应用程序 在该程序中定义一个学生类和班级类 以处理每个学生的学号 姓名 语文 数学和英语3门课程的期末考试成绩 要求 1 能根据姓名查询指定学生的总成绩 2 能统计全班学生的平均成绩 3 能统计单科成绩最高分 4 能统
  • Unity处决动画实现思路

    前言 不只是处决动画 只要是需要多个动画目标配合的都可以参考下面的思路 方案一 去除掉动画的位移部分 xz 在合适的时机移动到固定的位置双方同时播放动画 比如实现下图中狼和鹿的捕猎动画 我的做法是在要开始播放处决动画之前先让狼位移到固定位置
  • 卷积相关知识

    二维图片卷积 二维卷积可以处理二维数据 nn Conv2d self in channels out channels kernel size stride 1 padding 0 dilation 1 groups 1 bias True
  • 树莓派安装教程

    1 安装raspbian操作系统 下载安装工具 Win32DiskImager 0 9 5 binary 下载 img文件 使用上述工具即可 下载前首先需要格式化SD卡 再重新写入 之后插入SD卡 即可可以看到操作系统的界面 关于解决显示屏
  • 浅记封装的antd组件: 树形下拉选择

    树形下拉选择 1 可输入搜索 2 可设置单选多选 3 父节点选择后 可以设置子节点全选 import React from react import connect from dva import TreeSelect Form from
  • NeuPhysics: Editable Neural Geometry and Physics from Monocular Videos 解读

    1 论文简介 1 将NeRF和SDF方法结合来更好的回归物体表面 mesh 2 通过在神经辐射场后嵌入可微模拟器 实现动力学参数学习和进行场景编辑 2 核心思想 上述论文包含三个模块 1 Time invariant information
  • matlab生成dll

    实验室的一个项目需要调用matlab程序 经过再三考虑 决定使用vc调用matlab导出库的形式 而我主要负责与matlab程序结合的工作 以下是今天工作的简要总结 全当是个备忘吧 1 在matlab中选择compiler 在命令行窗口输入
  • 中国科学信息科学latex模板编译报错的解决办法

    中国科学 信息科学 latex模板编译不通过解决办法 1 前言 本文的解决办法不需要重新下载ctex 只需要添加两个文件即可 主要参考了下面的这篇文章如果你想知道为什么要这么改 强烈推荐阅读这篇博客 编译 CCT 模板 stone zeng
  • Django 模板的导入与继承

    目录 模板的导入和继承 1 模板的导入之include标签 2 模板的继承 派生之extendds标签 block标签 模板的导入和继承 在实际开发中 模板文件彼此之间可能会有大量冗余代码 为此django提供了专门的语法来解决这个问题 主
  • AIGC之GPT-4:GPT-4的简介与详细攻略

    AIGC之GPT 4 GPT 4的简介与详细攻略 简介 欢迎来到人工智能生成内容 AIGC 时代的新篇章 本篇博客将介绍GPT 4 Generative Pre trained Transformer 4 的核心原理 意义 亮点 技术点 缺
  • 【java笔记】泛型定义和使用

    为什么使用泛型 泛型的字面意思就是广泛的类型 利用泛型 同一套代码可以用于多种数据类型 这样 不仅可以复用代码 降低耦合 而且可以提高代码的可读性和安全性 可读性 var s new ArrayList
  • 【OpenGL进阶】04.支持多贴图的Shader

    这篇文章来实现一下多贴图的效果 在这篇文章中 再次对代码进行了封装 是代码看起来更加清晰明了 shader h中添加了SetTexture接口 pragma once include ggl h struct UniformTexture