[SOLVED] OpenGL Texture working in a weird way

Started by
8 comments, last by CubeSauce 6 years, 2 months ago

I've been dabbling in OpenGL for a past few days, and I've made a simple renderer which can display textures. Then after some time I realized that that will be too slow for a full game so i started researching Batching. I have successfully rendered a triangle/rect and managed to get it colored (whilst batching), but the texture have stumped me for a day.  For my texture loading reference I used this OpenGL tutorial. This is the picture I'm trying to render:

 sample.png.38f1508a6de4a804544cb4238434af05.png

When I start my project, this is what happens:

image.png.895724216125585e7ae0676b250f2714.png

I have tried to change the RGB to RGBA settings and so and nothing seemed to work. Also when i remove the


glBindTexture()

, the result is the same.

Here is my code:

Main.cpp

There is some initialization, but I doubt that'll be necessary.


VertexData one;
one.vertex	= glm::vec2(-0.5f, 0.5f);
one.color	= glm::vec3(1.0f, 0.0f, 0.0f);
one.texcoord = glm::vec2(0.0f, 0.0f);
VertexData two;
two.vertex	= glm::vec2(0.5f, 0.5f);
two.color	= glm::vec3(0.0f, 1.0f, 0.0f);
one.texcoord = glm::vec2(1.0f, 0.0f);
VertexData three;
three.vertex = glm::vec2(0.5f, -0.5f);
three.color	= glm::vec3(0.0f, 0.0f, 1.0f);
one.texcoord = glm::vec2(1.0f, 1.0f);
VertexData four;
four.vertex	= glm::vec2(-0.5f, -0.5f);
four.color	= glm::vec3(1.0f, 1.0f, 1.0f);
one.texcoord = glm::vec2(0.0f, 1.0f);


Shader shader(vertexSource, fragmentSource);

Batch renderer(shader);

while (!glfwWindowShouldClose(game.getWindow())) {
    glfwPollEvents();
    if (glfwGetKey(game.getWindow(), GLFW_KEY_ESCAPE) == GLFW_PRESS)
    glfwSetWindowShouldClose(game.getWindow(), GL_TRUE);

    renderer.Begin();

    renderer.Submit(&one);
    renderer.Submit(&two);
    renderer.Submit(&three);

    renderer.Submit(&three);
    renderer.Submit(&four);
    renderer.Submit(&one);

    renderer.End();

	glfwSwapBuffers(game.getWindow());
}

Batch.h


#pragma once
#include <GL\glew.h>
#include <iostream>
#include <SOIL2\SOIL2.h>

#include "Renderer.h"
#include "Shader.h"
#include "VertexArray.h"
#include "VertexBuffer.h"
#include "VertexBufferLayout.h"

#define RENDERER_MAX_VERTICES 10
#define WINWIDTH 800
#define WINHEIGHT 600

struct VertexData
{
	glm::vec2 vertex;
	glm::vec3 color;
	glm::vec2 texcoord;
};

class Batch
{
private:
	Renderer	 m_Renderer;
	unsigned int shaderProgram;
	unsigned int _vbo;
	unsigned int _vao;
	VertexData	*_buffer;
	unsigned int _vertexCount;
	bool		 m_Drawing;
public:
	Batch(Shader &shader)
		:_vertexCount(0), shaderProgram(shader.getProgram())
	{
		glGenBuffers(1, &_vbo);
		glGenVertexArrays(1, &_vao);

		glBindVertexArray(_vao);
		glBindBuffer(GL_ARRAY_BUFFER, _vbo);

		glBufferData(GL_ARRAY_BUFFER, RENDERER_MAX_VERTICES * sizeof(VertexData), NULL, GL_DYNAMIC_DRAW);

		// Specify the layout of the vertex data
		GLint posAttrib = glGetAttribLocation(shaderProgram, "position");
		glEnableVertexAttribArray(posAttrib);
		glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 7 * sizeof(GLfloat), 0);

		GLint colAttrib = glGetAttribLocation(shaderProgram, "color");
		glEnableVertexAttribArray(colAttrib);
		glVertexAttribPointer(colAttrib, 3, GL_FLOAT, GL_FALSE, 7 * sizeof(GLfloat), (void*)(2 * sizeof(GLfloat)));

		GLint texAttrib = glGetAttribLocation(shaderProgram, "texcoord");
		glEnableVertexAttribArray(texAttrib);
		glVertexAttribPointer(texAttrib, 2, GL_FLOAT, GL_FALSE, 7 * sizeof(GLfloat), (void*)(5 * sizeof(GLfloat)));


		// Load texture
		GLuint tex;
		glGenTextures(1, &tex);
		glBindTexture(GL_TEXTURE_2D, tex);

		int width, height;
		unsigned char* image = SOIL_load_image("sample.png", &width, &height, 0, SOIL_LOAD_RGB);
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
		SOIL_free_image_data(image);

		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

		glBindBuffer(GL_ARRAY_BUFFER, 0);
		glBindVertexArray(0);
	}

	~Batch()
	{
	}

	void Begin()
	{
		glBindBuffer(GL_ARRAY_BUFFER, _vbo);
		_buffer = (VertexData*)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
	}

	void Submit(VertexData* data)
	{
		*_buffer = *data;
		_buffer++;
		_vertexCount++;
	}

	void End()
	{
		glUnmapBuffer(GL_ARRAY_BUFFER);
		glBindBuffer(GL_ARRAY_BUFFER, 0);

		glClear(GL_COLOR_BUFFER_BIT);
		glBindVertexArray(_vao);
		glUseProgram(shaderProgram);
		glDrawArrays(GL_TRIANGLES, 0, _vertexCount);
		glBindVertexArray(0);

		_vertexCount = 0;
	}
};

Vertex and Fragment shaders


// Shader sources
const GLchar* vertexSource = R"glsl(
    #version 150 core
    in vec2 position;
    in vec3 color;
    in vec2 texcoord;
    out vec3 Color;
    out vec2 Texcoord;
    void main()
    {
        Color = color;
        Texcoord = texcoord;
        gl_Position = vec4(position, 0.0, 1.0);
    }
)glsl";
  
const GLchar* fragmentSource = R"glsl(
    #version 150 core
    in vec3 Color;
    in vec2 Texcoord;
    out vec4 outColor;
    uniform sampler2D tex;
    void main()
    {
        outColor = texture(tex, Texcoord) * vec4(Color, 1.0);
    }
)glsl";

I thank everyone in advance who tries to help :-), also im open to some optimization or better technique suggestions.

Matija Martinec @ Zagreb

Advertisement

You're only 4 vertices, two triangles should have 6.

Try using GL_QUADS (wich I think is deprecated on newer versions of opengl) or GL_TRIANGLE_STRIP, or specify elements using an GL_ELEMENT_ARRAY_BUFFER and draw using glDrawElements

If you look closer, im actually asigning the 6 vertices, and they are properly rendered, as you can see by the submit in the main function. and gl draw elements would be kinda stupid, because this is batch rendering, and let's say i want to render 10000+ sprites, that means at least 60000 elements (too much).

But thank you for your reply, but I't doesn't work I already tried it.

Matija Martinec @ Zagreb

You're assigning texture coordinates to the first vertex 4 times and not setting the others at all?

Derp

OMG HAhahahha,

1 minute ago, Sponji said:

You're assigning texture coordinates to the first vertex 4 times and not setting the others at all?

Thank you sponji..... I feel very stupid right now....

Matija Martinec @ Zagreb

Side note, your texture parameters must be specified before creating the actual texture with any glTexImage* functions.

Thanks for the tip, but I don't think it matters, because everything is still working. Could you please elaborate why or give me some links to why is it so? Thank you :-)

Matija Martinec @ Zagreb

Don't have any links to share right now, but I've experience cases ( I want to say on AMD HW ) in the past where the texture parameters would not reflect unless specified before the call to create the texture store. That is not to say the texture would not display as the default params  would be enough. A quick test would be to change the filtering/wrap mode to see. However, if all is working well for you then now worries then.

Oh, interesting. Thank you very much :-)

Matija Martinec @ Zagreb

This topic is closed to new replies.

Advertisement