我正在尝试在openGL中加载多个纹理。 为了验证这一点,我想加载2个纹理并将其与以下片段着色器混合:
#version 330 core
out vec4 color;
in vec2 v_TexCoord;
uniform sampler2D u_Texture0;
uniform sampler2D u_Texture1;
void main()
{
color = mix(texture(u_Texture0, v_TexCoord), texture(u_Texture1, v_TexCoord), 0.5);
}
我将OpenGL的功能抽象到Shader
,Texture
UniformXX
等类中。
这里尝试将2个纹理加载到片段的采样器单元中:
Shader shader;
shader.Attach(GL_VERTEX_SHADER, "res/shaders/vs1.shader");
shader.Attach(GL_FRAGMENT_SHADER, "res/shaders/fs1.shader");
shader.Link();
shader.Bind();
Texture texture0("res/textures/container.jpg", GL_RGB, GL_RGB);
texture0.Bind(0);
Uniform1i textureUnit0Uniform("u_Texture0");
textureUnit0Uniform.SetValues({ 0 });
shader.SetUniform(textureUnit0Uniform);
Texture texture1("res/textures/awesomeface.png", GL_RGBA, GL_RGBA);
texture1.Bind(1);
Uniform1i textureUnit1Uniform("u_Texture1");
textureUnit1Uniform.SetValues({ 1 });
shader.SetUniform(textureUnit1Uniform);
Texture
实现如下所示:
#include "Texture.h"
#include "Renderer.h"
#include "stb_image/stb_image.h"
Texture::Texture(const std::string& path, unsigned int destinationFormat, unsigned int sourceFormat)
: m_Path(path)
{
stbi_set_flip_vertically_on_load(1);
m_Buffer = stbi_load(path.c_str(), &m_Width, &m_Height, &m_BPP, 0);
GLCALL(glGenTextures(1, &m_RendererID));
GLCALL(glBindTexture(GL_TEXTURE_2D, m_RendererID));
GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT));
GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT));
GLCALL(glTexImage2D(GL_TEXTURE_2D, 0, destinationFormat, m_Width, m_Height, 0, sourceFormat, GL_UNSIGNED_BYTE, m_Buffer));
glGenerateMipmap(GL_TEXTURE_2D);
GLCALL(glBindTexture(GL_TEXTURE_2D, 0));
if (m_Buffer)
stbi_image_free(m_Buffer);
}
Texture::~Texture()
{
GLCALL(glDeleteTextures(1, &m_RendererID));
}
void Texture::Bind(unsigned int unit) const
{
GLCALL(glActiveTexture(GL_TEXTURE0 + unit));
GLCALL(glBindTexture(GL_TEXTURE_2D, m_RendererID));
}
void Texture::Unbind() const
{
GLCALL(glBindTexture(GL_TEXTURE_2D, 0));
}
现在,我并没有从两个纹理中获得均匀的颜色混合,而是只出现了第二个纹理并与背景混合:
我已经将问题定位到constructor
实现的Texture
,如果我注释掉第二个纹理的初始化,例如从未调用它的constructor
,那么我可以显示第一个纹理。
有人可以暗示我在做什么吗?
答案 0 :(得分:2)
花点时间找我,但是在您调用第二个纹理的构造函数时,您的活动纹理单位仍为0,因此构造函数很高兴地指向您的纹理单位,而您剩下两个绑定到相同纹理的纹理单元。
解决方案应该足够简单:首先创建纹理,然后仅然后显式绑定它们,不要交错纹理创建和纹理单元分配。
更好的是,考虑使用direct state access来避免所有这种绑定。
为了向以后的读者强调这个问题,这是有问题的通话顺序:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_fonts, container, false);
itemList = new ArrayList<FontItem>();
EditText editText = getActivity().findViewById(R.id.edit_text);
itemArrayAdapter = new ItemArrayAdapter(R.layout.recyclerview_item, itemList);
recyclerView = (RecyclerView) view.findViewById(R.id.font_list);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(itemArrayAdapter);
getListForRv(10);
editText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(itemArrayAdapter);
getListForRv(90);
itemArrayAdapter.notifyDataSetChanged();
}
@Override
public void afterTextChanged(Editable s) {
}
});
return view;
}
private void getListForRv(int k) {
if (!itemList.isEmpty())
itemList.clear();
for (int i = k; i < 1000; i++) {
itemList.add(new FontItem("Item " + i));
}
}