我正在努力发送多个纹理到一个单一的着色器,并有一个奇怪的问题,在着色器中的两个采样器似乎得到相同的纹理数据。我知道还有很多其他的多纹理问题和答案(这里有一些我已经读过很多次了1,2,3),但一些bug正在逃避我,我开始失去我的弹珠。我很有信心我已经把一切都安排好了,但显然还是有一些问题。
所以,目前我有形状,材料,纹理,和着色器类。我的shape类是执行实际绘制的父类。它有一个具有着色器和纹理数组的材料成员。material类绘制如下所示:
void Shape::Draw(GLenum mode, glm::mat4& model, glm::mat4& view, glm::mat4& proj)
{
m_Material.Enable();
m_Material.UpdateTransform(model, view, proj);
glBindVertexArray(m_VAO);
glDrawElements(mode, m_NumVerts, GL_UNSIGNED_INT, 0);
m_Material.Disable();
}
以下是我的整个材料课:
#include "pch.h"
#include "Material.h"
Material::Material() :
m_LightService(LightService::GetInstance())
{
OGLR_CORE_INFO("CREATING MATERIAL");
}
void Material::SetShader(std::string fileName)
{
m_Shader.SetShaderFileName(fileName);
}
void Material::Enable() {
m_Shader.Bind();
for (const auto text : m_Textures) {
text->Enable();
}
UploadUniforms();
}
void Material::Disable() {
m_Shader.Unbind();
for (const auto text : m_Textures) {
text->Disable();
}
}
void Material::AddTexture(std::string fileName, std::string typeName) {
m_Textures.push_back(std::make_shared<Texture>(fileName, m_Shader.ShaderId(), typeName, m_Textures.size()));
}
void Material::UpdateTransform(glm::mat4& model, glm::mat4& view, glm::mat4& proj) {
m_Shader.UploadUniformMat4("u_Projection", proj);
m_Shader.UploadUniformMat4("u_View", view);
m_Shader.UploadUniformMat4("u_Model", model);
}
void Material::UploadUniforms() {
if (m_Shader.isLoaded()) {
auto ambient = m_LightService->GetAmbientLight();
m_Shader.UploadUniformFloat3("uAmbientLight", ambient.strength * ambient.color);
}
}
void Material::SetMaterialData(std::shared_ptr<MaterialData> matData) {
AddTexture(matData->ambient_texname, "t_Ambient"); // Wall
AddTexture(matData->diffuse_texname, "t_Diffuse"); // Farm
}
正如您所看到的,当material从我们在material::SetMaterialData函数中呈现的。obj的。mtl文件中接收到material数据时,我们将向纹理列表中添加两个新的纹理对象。我们正在传入要加载的文件名和glsl统一采样器的字符串标识符。
当材质被启用时,我们将启用着色器和每个纹理对象。
这是我的纹理类的wip。
#include "pch.h"
#include "Texture.h"
#include <stb_image.h>
Texture::Texture(std::string fileName, uint32_t programId, std::string uniformId, uint16_t unitId)
{
m_FileName = ASSET_FOLDER + fileName;
unsigned char* texData = stbi_load(m_FileName.c_str(), &m_Width, &m_Height, &m_NrChannels, 0);
m_ProgramId = programId;
glUniform1i(glGetUniformLocation(programId, uniformId.c_str()), unitId);
glGenTextures(1, &m_TextureId);
m_TextureUnit = GL_TEXTURE0 + unitId;
glActiveTexture(m_TextureUnit);
glBindTexture(GL_TEXTURE_2D, m_TextureId);
if (texData)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, m_Width, m_Height, 0, GL_RGB, GL_UNSIGNED_BYTE, texData);
glGenerateMipmap(GL_TEXTURE_2D);
}
else
{
OGLR_CORE_ERROR("Failed to load texture");
throw std::runtime_error("Failed to load texture: "+ m_FileName);
}
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);
stbi_image_free(texData);
Disable();
}
void Texture::Enable()
{
glActiveTexture(m_TextureUnit); // activate the texture unit first before binding texture
glBindTexture(GL_TEXTURE_2D, m_TextureId);
}
void Texture::Disable()
{
glBindTexture(GL_TEXTURE_2D, 0);
}
所以,我做的第一件事是从着色器中获取采样器制服的ID,并将该样本绑定到我要寻找的纹理单元。然后我们生成纹理,激活相同的单元,并将生成的纹理绑定到它。我猜是在这里的某个地方我犯了错误,但我似乎不知道是怎么回事。
这是我的着色器,因为他们目前的立场。
// vertex
#version 330 core
layout (location = 0) in vec3 a_Position;
layout (location = 1) in vec3 aNormal;
layout (location = 2) in vec2 aTexCoord;
out vec3 outNormal;
out vec2 TexCoord;
uniform mat4 u_Projection;
uniform mat4 u_View;
uniform mat4 u_Model;
void main() {
vec4 worldPosition = u_Model * vec4(a_Position,1.0);
gl_Position = u_Projection * u_View * worldPosition;
outNormal = aNormal;
TexCoord = aTexCoord;
}
// fragment
#version 330 core
out vec4 color;
in vec3 outNormal;
in vec2 TexCoord;
uniform sampler2D t_Ambient;
uniform sampler2D t_Diffuse;
void main() {
if (TexCoord.x > 0.50)
{
//color = vec4(TexCoord.x, TexCoord.y, 0.0, 1.0);
color = texture(t_Diffuse, TexCoord);
}
else
{
color = texture(t_Ambient, TexCoord);
}
}
我希望我的三角形的每一半有不同的纹理,但出于某种原因,两个采样器似乎得到了相同的纹理。如果我在frag着色器中使用那个颜色而不是纹理,我得到一半的纹理和一半的颜色,所以它...至少有用...
我注意到的另一件事是,我觉得奇怪的是,得到渲染的纹理似乎总是我添加的第一个。如果我在Material::SetMaterialData中翻转AddTexture调用的顺序,另一个纹理就会出现。也许有人可以向我解释为什么这是显而易见的,但我本以为,如果我在绑定纹理时搞砸了,那么它将是第二个覆盖第一个的纹理,但嘿()_/'我已经准备好接受这方面的教育了。
编辑
我很抱歉,但显然不清楚着色器是否被正确绑定。
在shape::draw函数的开头,我们调用m_material.enable();
开头调用m_shader.bind();
,然后调用gluseprogramm(m_ProgramId);
很抱歉有任何混淆。
glUniform1i仅为当前启用的着色器绑定制服:
glUniform对通过调用GluseProgram而成为当前状态一部分的program对象进行操作。
在gluniform1i(glGetUniformLocation(programId,uniformid.c_str()),unitId)之前,似乎没有调用
(如果没有gluseprogram
;setMaterialData
)的调用者代码,我就不能确定了),而且该uniform实际上并没有绑定到着色器的unitId
。
所以试试这个:
glUseProgram(programId);
glUniform1i(glGetUniformLocation(programId, uniformId.c_str()), unitId);
glGenTextures(1, &m_TextureId);
如何在平面上滚动纹理?所以我有一个平面有一个纹理,我可以使用一个着色器滚动左从右(无限)的纹理上?
我希望能够在GLSL片段着色器中组合两种纹理。我目前正在使用PyOpenGL,到目前为止我使用着色器所做的一切都很好。 当我尝试从片段着色器访问多个纹理时遇到困难,例如,以下着色器显示正确的纹理减去蓝色像素: 但是 导致空白屏幕。 我有一种感觉,问题可能在于我如何将纹理制服传递给着色器,但我一辈子都无法弄清楚为什么第一个纹理有效,而第二个纹理无效。下面是完整的程序。
我在Mac OSX下工作,试图通过GLSL着色器在立方体上映射图像。 我显示立方体(以及图像,当它不通过着色器时)的方法是: 正如你所看到的,我正在检查,在这个测试中,是否有一个着色器应用到我的对象上(它是一个包装,效果非常好) 如果没有着色器,我只启用GL_纹理_坐标_数组,如果有,我尝试将图像绑定到着色器中的采样2D均匀。 我使用的着色器非常简单:它只显示纹理。我在Quartz Compose
在一个教程之后,我将尝试使用FreeType在OpenGL中渲染文本。因此,灰度8位图像用作每个字符的纹理,使图像的每个字节对应于纹理的红色分量。 为了以其他颜色呈现文本,建议您使用着色器。但是,当使用提供的着色器时,我看到的不是彩色字母,而是彩色框,好像根本没有纹理。 以下是没有着色器时的效果: 这是它在着色器中的外观: (盒子的位置也会发生变化) 以下是顶点着色器代码: 这是片段着色器代码:
目前,我有问题与传递多个纹理到一个glsl着色器在iOS。 在渲染中,想要的纹理被绑定到制服上 我在这里一直使用GL_TEXTURE0和GL_TEXTURE1,因为当纹理(实际上是来自iPhone摄像头的luma和Chroma纹理,最终用于计算相应的rgb值)被创建时,这些textureLots被使用。 我使用的fragmentshader非常简单,它只是用给定的纹理对一个简单的屏幕填充四方进行纹
我是OpenGL的新手,在整理如何将纹理和着色器绑定到VBOs时遇到了困难。 我正在使用Cinder的纹理和着色器类。以下是我绘制方法的一部分: 在上面的代码中,如果我注释掉对mShader的调用。bind(),我的球体VBO将显示纹理(myImage)。我的着色器适用于普通(无纹理)形状,但当我在绘制任何带有包裹纹理的形状之前绑定着色器时,它会阻止纹理显示。 这是我使用的着色器的问题,还是我不理