Partage
  • Partager sur Facebook
  • Partager sur Twitter

OpenGL, dessiner plusieurs fois la même forme

glDrawArraysInstanced

Sujet résolu
14 octobre 2018 à 17:50:57

Bonjour, après avoir suivi le tuto de Boouh, je souhaiterais afficher plusieurs fois la même forme (un grand nombre de fois), j'ai vu qu'il fallait utiliser la fonction glDrawArraysInstanced. Du coup j'ai réservé de la place sur GPU avec 

glBufferData(GL_ARRAY_BUFFER, m_verticesSize_Bytes + m_coordTextureSize_Bytes + m_nbCube*sizeof(glm::vec3), 0, GL_STATIC_DRAW);


puis j'y ai mis les données

glBufferSubData(GL_ARRAY_BUFFER, m_coordTextureSize_Bytes, m_nbCube*sizeof(glm::vec3), m_translations);

et après j'ai donné accès aux translations 

glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 3*sizeof(float), BUFFER_OFFSET(m_coordTextureSize_Bytes));
glEnableVertexAttribArray(3);
glVertexAttribDivisor(3, 1);


m_translations est un tableau de glm::vec3 ou on incrémente de 1 la coord x à chaque fois. Du coup pour le rendu j'utilise cette fonction

glDrawArraysInstanced(GL_TRIANGLES, 0, 36, m_nbCube);

Aussi, dans le shader j'ai ajouté la ligne suivante au chargement

glBindAttribLocation(m_programID, 3, "in_Offset");

Enfin le vertex shader ressemble à ça

// Version du GLSL

#version 150 core


// Entrées

in vec3 in_Vertex;
in vec2 in_TexCoord0;
in vec3 in_Offset;

// Uniform

uniform mat4 projection;
uniform mat4 modelview;


// Sortie

out vec2 coordTexture;

// Fonction main

void main()
{
    // Position finale du vertex en 3D

    gl_Position = projection * modelview * vec4(in_Vertex + in_Offset, 1.0);


    // Envoi des coordonnées de texture au Fragment Shader

    coordTexture = in_TexCoord0;
}


Et le résultat n'est pas bon, je vous laisse en juger :p

Merci de vos réponses :)

  • Partager sur Facebook
  • Partager sur Twitter
14 octobre 2018 à 18:30:12

Salut

glDrawInstanced ne requiert pas d'allouer un grand nombre de données à l'intérieur d'un VBO.

L'idée est la suivante : tu crées 2 VBO :

Un premier VBO qui contient les données de ton cube (grossièrement 8 sommets (positions, normal, texture, couleur etc)).

Un second VBO (ou un UBO) qui contient les matrices. Si tu choisis l'option VBO, là tu dois utiliser glVertexAttribDivisor mais n'oublie pas que tu dois fournir tes matrices à ton shader. Du coup tu te retrouverais à avoir quelque chose comme ça :

layout(location = 0) in vec3 position;
layout(location = 1) in vec3 normal;
layout(location = 2) in vec2 texCoord;

layout(location = 3) in mat4 worldMatrix;
// jusqu'à location 6

void main() {
    gl_Position = perspecive * view * worldMatrix * vec4(position, 1.0);
}

En gros, avant de vouloir faire fonctionner ton code sur de l'instancé : fais le fonctionner surr du normal (car la base de code sera la même) et ensuite tu rajoutes l'instancing. Toi j'ai l'impression que tu veux stocker les sommets de tout tes cubes dans un VBO, alors que le but de l'instancing est justement d'éviter de faire ça : tu stockes ton cube dans un VBO, et les informations de position dans des buffers annexe (SSBO, UBO, ou VBO avec divisor;) )

  • Partager sur Facebook
  • Partager sur Twitter
http://cpp-rendering.io : Vous trouverez tout ce dont vous avez besoin sur Vulkan / OpenGL et le rendu 3D !
14 octobre 2018 à 19:35:18

Merci de ta réponse mais je ne comprends pas bien ce qu'est worldMatrix dans ton exemple. Dans le tuto, on stocke bien les données du cube dans un vbo, mais les matrices sont transmises dans la fonction dessiner. Ce que j'ai fait c'est de rajouter dans le vbo un tableau de vecteurs de translation (en les envoyant 1 par 1, donc 3 floats à chaque fois, enfin j'espère) et après dans le shader j'ajoute à la position la translation en question. Je link le code de la fonction chager

if (glIsBuffer(m_vboID) == GL_TRUE)
			glDeleteBuffers(1, &m_vboID);
		glGenBuffers(1, &m_vboID);


		// Verrouillage du VBO

		glBindBuffer(GL_ARRAY_BUFFER, m_vboID);


		// Allocation de la mémoire vidéo

			glBufferData(GL_ARRAY_BUFFER, m_verticesSize_Bytes + m_coordTextureSize_Bytes + m_nbCube*sizeof(glm::vec3), 0, GL_STATIC_DRAW);

			// Transfert des données

			glBufferSubData(GL_ARRAY_BUFFER, 0, m_verticesSize_Bytes, m_vertices);
			glBufferSubData(GL_ARRAY_BUFFER, m_verticesSize_Bytes, m_coordTextureSize_Bytes, m_coordTexture);
			glBufferSubData(GL_ARRAY_BUFFER, m_coordTextureSize_Bytes, m_nbCube*sizeof(glm::vec3), m_translations);


			// Déverrouillage de l'objet

		glBindBuffer(GL_ARRAY_BUFFER, 0);


		if (glIsVertexArray(m_vaoID) == GL_TRUE)
			glDeleteVertexArrays(1, &m_vaoID);
		glGenVertexArrays(1, &m_vaoID);		

		//Verrouillage du VAO

		glBindVertexArray(m_vaoID);

			//Verrouillage du VBO

			glBindBuffer(GL_ARRAY_BUFFER, m_vboID);


				// Accès aux vertices dans la mémoire vidéo

				glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
				glEnableVertexAttribArray(0);


				// Accès aux couleurs dans la mémoire vidéo

				glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(m_verticesSize_Bytes));
				glEnableVertexAttribArray(2);

				//Accès aux offsets
				glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 3*sizeof(float), BUFFER_OFFSET(m_coordTextureSize_Bytes));
				glEnableVertexAttribArray(3);
				glVertexAttribDivisor(3, 1);


			// Déverrouillage du VBO

			glBindBuffer(GL_ARRAY_BUFFER, 0);

		//Déverrouillage du VAO

		glBindVertexArray(0);

et de dessiner

glUseProgram(m_shader.getProgramID());

			glBindVertexArray(m_vaoID);

				glUniformMatrix4fv(glGetUniformLocation(m_shader.getProgramID(), "projection"), 1, GL_FALSE, value_ptr(projection));
				glUniformMatrix4fv(glGetUniformLocation(m_shader.getProgramID(), "modelview"), 1, GL_FALSE, value_ptr(modelview));

				glBindTexture(GL_TEXTURE_2D, m_texture.getId());

					glDrawArraysInstanced(GL_TRIANGLES, 0, 36, m_nbCube);

				glBindTexture(GL_TEXTURE_2D, 0);

			glBindVertexArray(0);

		glUseProgram(0);


Tu voudrais que je stocke les matrices modelview et projection dans un autre vbo pour les envoyer au shader ? Avec une ligne de ce style par exemple ?

glVertexAttribPointer(4, 16, GL_FLOAT, GL_FALSE, 16*sizeof(float), BUFFER_OFFSET(0));
				glEnableVertexAttribArray(4); 

pour le 16*sizeof(float) je n'en suis pas sûr je me dis que c'est pour associer une seule modelview à chaque vertex, par exemple si j'avais mis 0 ça aurait considérer que la position 4 était un float ? Aussi, le tuto que j'ai vu pour gérer ce genre de cas (en 2D) est ici


EDIT : je viens de me rendre compte que j'envoie une translation pour chaque vertex et pas pour chaque cube mais du coup je ne sais pas le faire...

-
Edité par Gypso2 14 octobre 2018 à 20:03:18

  • Partager sur Facebook
  • Partager sur Twitter
14 octobre 2018 à 20:55:25

Alors en gros faudrait appeler 4 fois glVertexAttribPointer pour envoyer les 4 colonnes de ta matrice oui.

Et pour pas envoyer chaque colonnes de ta matrice à chaque vertex, faut utiliser le divisor ;).

Dans ton exemple, tu restes sur un VBO qui contient les informations du cube. Tu créés un VBO qui contient tes translations pour lequel tu appliques un divisor (afin qu'il soit envoyé à chaque instance et non pas à chaque vertex ;) ).

  • Partager sur Facebook
  • Partager sur Twitter
http://cpp-rendering.io : Vous trouverez tout ce dont vous avez besoin sur Vulkan / OpenGL et le rendu 3D !
14 octobre 2018 à 22:17:27

J'ai rajouté un vbo et maintenant je n'ai plus un cube déformé, mais juste le cube normal (avec textures). Le code :

méthode charger

if (glIsBuffer(m_vboID) == GL_TRUE)
			glDeleteBuffers(1, &m_vboID);
		glGenBuffers(1, &m_vboID);

		if (glIsBuffer(m_vboID2) == GL_TRUE)
			glDeleteBuffers(1, &m_vboID2);
		glGenBuffers(1, &m_vboID2);

		if (glIsVertexArray(m_vaoID) == GL_TRUE)
			glDeleteVertexArrays(1, &m_vaoID);
		glGenVertexArrays(1, &m_vaoID);



		glBindBuffer(GL_ARRAY_BUFFER, m_vboID2);

			glBufferData(GL_ARRAY_BUFFER, 3*m_nbCube*sizeof(float), m_translations, GL_STATIC_DRAW);

		glBindBuffer(GL_ARRAY_BUFFER, 0);


		// Verrouillage du VBO

		glBindBuffer(GL_ARRAY_BUFFER, m_vboID);

			glBufferData(GL_ARRAY_BUFFER, m_verticesSize_Bytes + m_coordTextureSize_Bytes, 0, GL_STATIC_DRAW);
			glBufferSubData(GL_ARRAY_BUFFER, 0, m_verticesSize_Bytes, m_vertices);
			glBufferSubData(GL_ARRAY_BUFFER, m_verticesSize_Bytes, m_coordTextureSize_Bytes, m_coordTexture);

		glBindBuffer(GL_ARRAY_BUFFER, 0);


			

		//Verrouillage du VAO

		glBindVertexArray(m_vaoID);

			//Verrouillage du VBO

			glBindBuffer(GL_ARRAY_BUFFER, m_vboID);
				
				glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
				glEnableVertexAttribArray(0);

				glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(m_verticesSize_Bytes));
				glEnableVertexAttribArray(2);
				
			//Verouillage du VBO2

			glBindBuffer(GL_ARRAY_BUFFER, m_vboID2);

				glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(m_coordTextureSize_Bytes));
				glEnableVertexAttribArray(3);
				glVertexAttribDivisor(3, 36); //tous les 36 vertices

			glBindBuffer(GL_ARRAY_BUFFER, 0);

		//Déverrouillage du VAO

		glBindVertexArray(0);

Du coup comme le cube est composé de 36 vertices et que j'envoie le vecteur translation une fois toutes les 36 instances, il devrait y avoir une translation par cube ? Merci. :)

  • Partager sur Facebook
  • Partager sur Twitter
14 octobre 2018 à 22:34:16

Salut.

Quand tu bind ton vao avec le VBO2. Pourquoi tu fais commencé ton buffer par un offset ? Ton buffer de translation commence à l'offset 0, pas à l'offset m_coordTextureSize_Bytes...

Tu n'as pas compris la fonction glVertexAttribDivisor. Tu ne comprends pas non plus le mot instance.

Un cube = 8 sommets. Un cube = 6 faces de 2 triangles = 12 faces = "36 sommets" à "traiter" par la carte graphique.

Une instance d'un cube c'est un cube. 2 instances signifie donc 2 cubes. 3 instances 3 cubes etc.

glVertexAttribDivisor attend en entrée le nombre d'instance à sauter. Dans ton cas tu lui dis d'avancer tout les 36 instances. C'est à dire que les 36 premières instances sont dessiné avec la même translation, les 36 suivants sont dessinés avec la translation d'après etc.

tu devrais donc donné glVertexAttribDivisor(3, 1);

Si tu veux que la même valeur soit assigné à 4 cubes par exemple, tu écris glVertexAttribDivisor(3, 4); Toi dans ton cas, c'est tout les 36 cubes qu'elle change ;)

D'ailleurs je viens de capter que tu utilises le numéro 0 2 3. Pourquoi ne pas utiliser plutôt 0 1 2 ?

Dans tes conventions de nommage VBOID VBOID2 ça veut rien dire. nomme tes variables correctement : cubeSommetVBO. TranslationVBO par exemple.

  • Partager sur Facebook
  • Partager sur Twitter
http://cpp-rendering.io : Vous trouverez tout ce dont vous avez besoin sur Vulkan / OpenGL et le rendu 3D !
14 octobre 2018 à 22:49:41

Pour l'offset c'est une erreur de c/c, j'avais bien compris mais je parlais d'instance de vec3, je croyais que ça traitait pour chaque vertice donc à faire 1 fois sur 36, d'ailleurs comment sait-il qu'il faut attendre que les 36 vertices soient traités si on met 1, comment ferait-on si on voulait que cela soit fait tous les 2 vertices dans le cube par exemple (et pas 2 cubes) ?  Est-ce que c'est lié au 3e paramètre de la fonction glDrawArraysInstanced ? Pour les numéros 0 2 3, j'utilise 1 pour les couleurs :). Dans shaper.cpp j'ai rajouté une ligne 
glBindAttribLocation(m_programID, 0, "in_Vertex");
glBindAttribLocation(m_programID, 1, "in_Color");
glBindAttribLocation(m_programID, 2, "in_TexCoord0");
glBindAttribLocation(m_programID, 3, "in_Offset");
Le résultat ne change pas.

-
Edité par Gypso2 14 octobre 2018 à 22:54:44

  • Partager sur Facebook
  • Partager sur Twitter
14 octobre 2018 à 23:03:38

Parce qu'en réalité je me suis mal exprimé. Une instance = une instance de triangle. Il y a 12 triangles par cube, donc une instance d'un cube = une instance des 12 triangles (12 petites instances si tu veux). Tu peux pas faire en fonction de 2 vertices et c'est normal car ça n'aurait aucun sens. Ou alors ce serait via un GL_LINES et pas un GL_TRIANGLES.

Pour glDrawArrayInstanced il suffit de regarder la doc :

le troisième paramètre c'est le nombre de sommet à processer donc surement 36 pour toi, et le quatrième paramètre c'est le nombre d'instance.

Qu'est ce qui ne marche pas? Peux tu me montrer ton code entier plutôt que des brides?

Tu ne devrais pas utiliser glBindAttribLocation, mais layout location à la place 

layout(location = 0) in vec3 in_Vertex;
layout(location = 1) in vec4 in_Color;
layout(location = 2) in vec2 in_TexCoord;
layout(location = 3) in vec3 in_Offset;

Comme ça ton code utilisant glBindAttribLocation n'est pas utile et tu gères tes locations directement dans le shader.

  • Partager sur Facebook
  • Partager sur Twitter
http://cpp-rendering.io : Vous trouverez tout ce dont vous avez besoin sur Vulkan / OpenGL et le rendu 3D !
14 octobre 2018 à 23:31:12

Voilà le code 

#pragma once
#include "Cube.h"
#include "texture.h"

#define BUFFER_OFFSET(offset) ((char*)NULL + (offset))

namespace ARW
{
	class TexturedCube: public ARW::Cube
	{
	protected:
		Texture m_texture;
		int m_coordTextureSize_Bytes;
		float m_coordTexture[72];
		int m_nbCube;
		float * m_translations;
		GLuint m_vboTranslationID;
	public:
		TexturedCube(float size, std::string const vertexShader, std::string const fragmentShader, std::string const texture);
		virtual void draw(glm::mat4 &projection, glm::mat4 &modelview);
		virtual void load();
		~TexturedCube();
	};
};




#include "TexturedCube.h"


namespace ARW
{
	
	TexturedCube::TexturedCube(float size, std::string const vertexShader, std::string const fragmentShader, std::string const texture) : Cube(size, vertexShader, fragmentShader), m_texture(texture) , m_coordTextureSize_Bytes(72*sizeof(int)), m_nbCube(10), m_vboTranslationID(0)
	{
		m_translations = (float*)malloc(3*m_nbCube * sizeof(float));
		
		m_texture.load();
		float coordTextureTmp[] = { 
									

									0, 0,   1, 0,   1, 1,
									0, 0,   0, 1,   1, 1,

									0, 0,   0, 1,   1, 1,
									0, 0,   1, 0,   1, 1,

									0, 0,   0, 1,   1, 1,
									0, 0,   1, 0,   1, 1,

									0, 0,   0, 1,   1, 1,
									0, 0,   1, 0,   1, 1,

									0, 0,   0, 1,   1, 1,
									0, 0,   1, 0,   1, 1,

									0, 0,   0, 1,   1, 1,
									0, 0,   1, 0,   1, 1
								};
		for (int i(0); i < 72; i++)
			m_coordTexture[i] = coordTextureTmp[i];	
		if (m_translations != nullptr)
		{
			for (int i = 0; i < m_nbCube; i++)
			{
				//translation de i sur x pour voir
				m_translations[i] = i;
				m_translations[i + 1] = 0.0;
				m_translations[i + 2] = 0.0;
			}
		}
		
	}

	void TexturedCube::draw(glm::mat4 &projection, glm::mat4 &modelview)
	{
		glUseProgram(m_shader.getProgramID());

			glBindVertexArray(m_vaoID);

				glUniformMatrix4fv(glGetUniformLocation(m_shader.getProgramID(), "projection"), 1, GL_FALSE, value_ptr(projection));
				glUniformMatrix4fv(glGetUniformLocation(m_shader.getProgramID(), "modelview"), 1, GL_FALSE, value_ptr(modelview));

				glBindTexture(GL_TEXTURE_2D, m_texture.getId());

					glDrawArraysInstanced(GL_TRIANGLES, 0, 36, m_nbCube);

				glBindTexture(GL_TEXTURE_2D, 0);

			glBindVertexArray(0);

		glUseProgram(0);
	}

	void TexturedCube::load()
	{
		if (glIsBuffer(m_vboCubeID) == GL_TRUE)
			glDeleteBuffers(1, &m_vboCubeID);
		glGenBuffers(1, &m_vboCubeID);

		if (glIsBuffer(m_vboTranslationID) == GL_TRUE)
			glDeleteBuffers(1, &m_vboTranslationID);
		glGenBuffers(1, &m_vboTranslationID);

		if (glIsVertexArray(m_vaoID) == GL_TRUE)
			glDeleteVertexArrays(1, &m_vaoID);
		glGenVertexArrays(1, &m_vaoID);



		glBindBuffer(GL_ARRAY_BUFFER, m_vboTranslationID);

			glBufferData(GL_ARRAY_BUFFER, 3*m_nbCube*sizeof(float), m_translations, GL_STATIC_DRAW);

		glBindBuffer(GL_ARRAY_BUFFER, 0);


		// Verrouillage du VBO

		glBindBuffer(GL_ARRAY_BUFFER, m_vboCubeID);

			glBufferData(GL_ARRAY_BUFFER, m_verticesSize_Bytes + m_coordTextureSize_Bytes, 0, GL_STATIC_DRAW);
			glBufferSubData(GL_ARRAY_BUFFER, 0, m_verticesSize_Bytes, m_vertices);
			glBufferSubData(GL_ARRAY_BUFFER, m_verticesSize_Bytes, m_coordTextureSize_Bytes, m_coordTexture);

		glBindBuffer(GL_ARRAY_BUFFER, 0);


			

		//Verrouillage du VAO

		glBindVertexArray(m_vaoID);

			//Verrouillage du VBO

			glBindBuffer(GL_ARRAY_BUFFER, m_vboCubeID);
				
				glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
				glEnableVertexAttribArray(0);

				glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(m_verticesSize_Bytes));
				glEnableVertexAttribArray(2);
				
			//Verouillage du VBO2

			glBindBuffer(GL_ARRAY_BUFFER, m_vboTranslationID);

				glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
				glEnableVertexAttribArray(3);
				glVertexAttribDivisor(3, 1); //tous les 36 vertices

			glBindBuffer(GL_ARRAY_BUFFER, 0);

		//Déverrouillage du VAO

		glBindVertexArray(0);
	}


	TexturedCube::~TexturedCube()
	{
		free(m_translations);
	}

};
// Version du GLSL

#version 150 core


// Entrées

in vec3 in_Vertex;
in vec2 in_TexCoord0;
in vec3 in_Offset

// Uniform

uniform mat4 projection;
uniform mat4 modelview;


// Sortie

out vec2 coordTexture;

// Fonction main

void main()
{
    // Position finale du vertex en 3D

    gl_Position = projection * modelview * vec4(in_Vertex + in_Offset, 1.0);


    // Envoi des coordonnées de texture au Fragment Shader

    coordTexture = in_TexCoord0;
}




Désolé d'avance pour le manque de lisibilité je ferai un truc propre quand ça marchera :)
Si j'utilise 
layout(location = 0) in vec3 in_Vertex;
layout(location = 1) in vec4 in_Color;
layout(location = 2) in vec2 in_TexCoord;
layout(location = 3) in vec3 in_Offset;
à la place des glBindAttribLocation ça ne m'affiche plus la texture correctement, mais une sorte de moyenne des couleurs, en bref c'est marron clair mais pas uniforme.

-
Edité par Gypso2 14 octobre 2018 à 23:33:45

  • Partager sur Facebook
  • Partager sur Twitter
15 octobre 2018 à 0:11:39

Ok ya vraiment un truc que je comprends pas. Je te demande de m'envoyer le code entier, tu me renvoies un code que je ne peux pas tester, pour lequel il manque la class Cube etc... je ne comprends toujours pas pourquoi tu t'entête à utiliser des color en unité 1 alors que tu ne t'en sers jamais.

Je ne comprends pas non plus pourquoi tu écris du C avec des classes ... Tu es en C++ pas en C, donc n'utilise jamais de malloc, de tableau à la C : (float tableau[72] = {}) et pleins d'autre trucs.

Pour ton problème en utilisant layout(location) c'est bizarre. A mon avis ça vient du faire que couleur n'est pas utilisé, mais je n'affirme pas.

Pour le reste je n'ai pas di'dée malheureusement...

Qu'est ce qu'il se passe si tu écris ça dans ton shader plutôt que ta ligne actuel ? :

gl_Position = projection * modelview * vec4(in_Vertex + vec3(gl_InstanceID, 0, 0), 1.0);



  • Partager sur Facebook
  • Partager sur Twitter
http://cpp-rendering.io : Vous trouverez tout ce dont vous avez besoin sur Vulkan / OpenGL et le rendu 3D !
15 octobre 2018 à 12:20:56

Pour la dernière ligne, ça ne fait rien. J'envoie le code

drawable.h

#pragma once

#define GLM_ENABLE_EXPERIMENTAL 1

#include <SFML\OpenGL.hpp>
#include <glm/glm.hpp>
#include <glm/gtx/transform.hpp>
#include <glm/gtc/type_ptr.hpp>

namespace ARW
{
	class Drawable
	{
	public:
		Drawable();
		virtual void draw(glm::mat4 &projection, glm::mat4 &modelview) = 0;
		virtual ~Drawable();
	};
};

drawable.cpp

#include "Drawable.h"


namespace ARW
{

	Drawable::Drawable()
	{
	}
	Drawable::~Drawable()
	{

	}
};

texture.h

#pragma once
#define GLM_ENABLE_EXPERIMENTAL 1

#include <SFML\Graphics\Image.hpp>
#include <SFML\OpenGL.hpp>
#include <glm/glm.hpp>
#include <glm/gtx/transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <iostream>
#include <string>

namespace ARW
{
	class Texture
	{
		GLuint m_id;
		std::string m_fileName;
	public:
		Texture();
		Texture(std::string fileName);
		GLuint getId() const;
		bool load();
		bool loadFromFile(std::string fileName);
		~Texture();
	};
};

texture.cpp

#include "texture.h"

namespace ARW
{
	
	Texture::Texture()
	{
	}

	Texture::Texture(std::string fileName): m_id(0), m_fileName(fileName)
	{
	}

	GLuint Texture::getId() const
	{
		return m_id;
	}

	bool Texture::load()
	{
		GLuint identifiant_texture = 0;
		sf::Image image;
		if (!image.loadFromFile(m_fileName))
		{
			std::cout << "[TEXTURE] Fail to load " << m_fileName << std::endl;
			return EXIT_FAILURE;
		}
			

		glGenTextures(1, &m_id);
		glBindTexture(GL_TEXTURE_2D, m_id);

			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.getSize().x, image.getSize().y, 0, GL_RGBA, GL_UNSIGNED_BYTE, image.getPixelsPtr());
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

		glBindTexture(GL_TEXTURE_2D, 0);

		return true;
	}

	bool Texture::loadFromFile(std::string fileName)
	{
		m_fileName = fileName;
		return load();
	}

	Texture::~Texture()
	{
	}

};


Shader.h

#pragma once

#include <GL/glew.h>
#include <SFML\OpenGL.hpp>

#include <iostream>
#include <string>
#include <fstream>


namespace ARW
{
	class Shader
	{
	public:

		Shader();
		Shader(Shader const &shaderACopier);
		Shader(std::string vertexSource, std::string fragmentSource);
		~Shader();

		Shader& operator=(Shader const &shaderACopier);

		bool load();
		bool compileShader(GLuint &shader, GLenum type, std::string const &fichierSource);
		GLuint getProgramID() const;


	private:

		GLuint m_vertexID;
		GLuint m_fragmentID;
		GLuint m_programID;

		std::string m_vertexSource;
		std::string m_fragmentSource;
	};
};

Shader.cpp

#include "Shader.h"

namespace ARW
{


	Shader::Shader() : m_vertexID(0), m_fragmentID(0), m_programID(0), m_vertexSource(), m_fragmentSource()
	{
	}


	Shader::Shader(Shader const &shaderACopier)
	{


		m_vertexSource = shaderACopier.m_vertexSource;
		m_fragmentSource = shaderACopier.m_fragmentSource;

		load();
	}


	Shader::Shader(std::string vertexSource, std::string fragmentSource) : m_vertexID(0), m_fragmentID(0), m_programID(0),
		m_vertexSource(vertexSource), m_fragmentSource(fragmentSource)
	{
	}


	Shader::~Shader()
	{

		glDeleteShader(m_vertexID);
		glDeleteShader(m_fragmentID);
		glDeleteProgram(m_programID);
	}


	Shader& Shader::operator=(Shader const &shaderACopier)
	{

		m_vertexSource = shaderACopier.m_vertexSource;
		m_fragmentSource = shaderACopier.m_fragmentSource;


		load();


		return *this;
	}


	bool Shader::load()
	{

		if (glIsShader(m_vertexID) == GL_TRUE)
			glDeleteShader(m_vertexID);

		if (glIsShader(m_fragmentID) == GL_TRUE)
			glDeleteShader(m_fragmentID);

		if (glIsProgram(m_programID) == GL_TRUE)
			glDeleteProgram(m_programID);


		if (!compileShader(m_vertexID, GL_VERTEX_SHADER, m_vertexSource))
		{
			std::cout << "Fail to compile vertex shader" << std::endl;
			return false;
		}
			

		if (!compileShader(m_fragmentID, GL_FRAGMENT_SHADER, m_fragmentSource))
		{
			std::cout << "Fail to compile fragment shader" << std::endl;
			return false;
		}
		m_programID = glCreateProgram();


		glAttachShader(m_programID, m_vertexID);
		glAttachShader(m_programID, m_fragmentID);


		glBindAttribLocation(m_programID, 0, "in_Vertex");
		glBindAttribLocation(m_programID, 1, "in_Color");
		glBindAttribLocation(m_programID, 2, "in_TexCoord0");
		glBindAttribLocation(m_programID, 3, "in_Offset");

		glLinkProgram(m_programID);


		GLint erreurLink(0);
		glGetProgramiv(m_programID, GL_LINK_STATUS, &erreurLink);


		if (erreurLink != GL_TRUE)
		{

			GLint tailleErreur(0);
			glGetProgramiv(m_programID, GL_INFO_LOG_LENGTH, &tailleErreur);


			char *erreur = new char[tailleErreur + 1];


			glGetShaderInfoLog(m_programID, tailleErreur, &tailleErreur, erreur);
			erreur[tailleErreur] = '\0';


			std::cout << erreur << std::endl;


			delete[] erreur;
			glDeleteProgram(m_programID);

			return false;
		}



		else
			return true;
	}


	bool Shader::compileShader(GLuint &shader, GLenum type, std::string const &fichierSource)
	{

		shader = glCreateShader(type);

		if (shader == 0)
		{
			std::cout << "Erreur, le type de shader (" << type << ") n'existe pas" << std::endl;
			return false;
		}


		std::ifstream fichier(fichierSource.c_str());


		if (!fichier)
		{
			std::cout << "Erreur le fichier " << fichierSource << " est introuvable" << std::endl;
			glDeleteShader(shader);

			return false;
		}


		std::string ligne;
		std::string codeSource;



		while (getline(fichier, ligne))
			codeSource += ligne + '\n';


		fichier.close();


		const GLchar* chaineCodeSource = codeSource.c_str();


		glShaderSource(shader, 1, &chaineCodeSource, 0);


		glCompileShader(shader);


		GLint erreurCompilation(0);
		glGetShaderiv(shader, GL_COMPILE_STATUS, &erreurCompilation);


		if (erreurCompilation != GL_TRUE)
		{

			GLint tailleErreur(0);
			glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &tailleErreur);


			char *erreur = new char[tailleErreur + 1];

			glGetShaderInfoLog(shader, tailleErreur, &tailleErreur, erreur);
			erreur[tailleErreur] = '\0';


			std::cout << erreur << std::endl;


			delete[] erreur;
			glDeleteShader(shader);

			return false;
		}


		else
			return true;
	}



	GLuint Shader::getProgramID() const
	{
		return m_programID;
	}
};

TexturedCube.h

#pragma once
#include "Cube.h"
#include "texture.h"

#define BUFFER_OFFSET(offset) ((char*)NULL + (offset))

namespace ARW
{
	class TexturedCube: public ARW::Cube
	{
	protected:
		Texture m_texture;
		int m_coordTextureSize_Bytes;
		float m_coordTexture[72];
		int m_nbCube;
		std::vector<float> m_translations;
		GLuint m_vboTranslationID;
	public:
		TexturedCube(float size, std::string const vertexShader, std::string const fragmentShader, std::string const texture);
		virtual void draw(glm::mat4 &projection, glm::mat4 &modelview);
		virtual void load();
		~TexturedCube();
	};
};


TextureCube.cpp

#include "TexturedCube.h"


namespace ARW
{
	
	TexturedCube::TexturedCube(float size, std::string const vertexShader, std::string const fragmentShader, std::string const texture) : Cube(size, vertexShader, fragmentShader), m_texture(texture) , m_coordTextureSize_Bytes(72*sizeof(float)), m_nbCube(10), m_vboTranslationID(0)
	{		
		m_texture.load();
		float coordTextureTmp[] = { 								
									0, 0,   1, 0,   1, 1,
									0, 0,   0, 1,   1, 1,

									0, 0,   0, 1,   1, 1,
									0, 0,   1, 0,   1, 1,

									0, 0,   0, 1,   1, 1,
									0, 0,   1, 0,   1, 1,

									0, 0,   0, 1,   1, 1,
									0, 0,   1, 0,   1, 1,

									0, 0,   0, 1,   1, 1,
									0, 0,   1, 0,   1, 1,

									0, 0,   0, 1,   1, 1,
									0, 0,   1, 0,   1, 1
								};
		for (int i(0); i < 72; i++)
			m_coordTexture[i] = coordTextureTmp[i];	
		for (int i = 0; i < m_nbCube; i++)
		{
			//translation de i sur x pour voir
			m_translations.push_back((float)i);
			m_translations.push_back(0.0);
			m_translations.push_back(0.0);
		}
	}

	void TexturedCube::draw(glm::mat4 &projection, glm::mat4 &modelview)
	{
		glUseProgram(m_shader.getProgramID());

			glBindVertexArray(m_vaoID);

				glUniformMatrix4fv(glGetUniformLocation(m_shader.getProgramID(), "projection"), 1, GL_FALSE, value_ptr(projection));
				glUniformMatrix4fv(glGetUniformLocation(m_shader.getProgramID(), "modelview"), 1, GL_FALSE, value_ptr(modelview));

				glBindTexture(GL_TEXTURE_2D, m_texture.getId());

					glDrawArraysInstanced(GL_TRIANGLES, 0, 36, m_nbCube);

				glBindTexture(GL_TEXTURE_2D, 0);

			glBindVertexArray(0);

		glUseProgram(0);
	}

	void TexturedCube::load()
	{
		if (glIsBuffer(m_vboCubeID) == GL_TRUE)
			glDeleteBuffers(1, &m_vboCubeID);
		glGenBuffers(1, &m_vboCubeID);

		if (glIsBuffer(m_vboTranslationID) == GL_TRUE)
			glDeleteBuffers(1, &m_vboTranslationID);
		glGenBuffers(1, &m_vboTranslationID);

		if (glIsVertexArray(m_vaoID) == GL_TRUE)
			glDeleteVertexArrays(1, &m_vaoID);
		glGenVertexArrays(1, &m_vaoID);



		glBindBuffer(GL_ARRAY_BUFFER, m_vboTranslationID);

			glBufferData(GL_ARRAY_BUFFER, 3*m_nbCube*sizeof(float), &m_translations[0], GL_STATIC_DRAW);

		glBindBuffer(GL_ARRAY_BUFFER, 0);


		// Verrouillage du VBO

		glBindBuffer(GL_ARRAY_BUFFER, m_vboCubeID);

			glBufferData(GL_ARRAY_BUFFER, m_verticesSize_Bytes + m_coordTextureSize_Bytes, 0, GL_STATIC_DRAW);
			glBufferSubData(GL_ARRAY_BUFFER, 0, m_verticesSize_Bytes, m_vertices);
			glBufferSubData(GL_ARRAY_BUFFER, m_verticesSize_Bytes, m_coordTextureSize_Bytes, m_coordTexture);

		glBindBuffer(GL_ARRAY_BUFFER, 0);


			

		//Verrouillage du VAO

		glBindVertexArray(m_vaoID);

			//Verrouillage du VBO

			glBindBuffer(GL_ARRAY_BUFFER, m_vboCubeID);
				
				glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
				glEnableVertexAttribArray(0);

				glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(m_verticesSize_Bytes));
				glEnableVertexAttribArray(2);
				
			//Verouillage du VBO2

			glBindBuffer(GL_ARRAY_BUFFER, m_vboTranslationID);

				glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
				glEnableVertexAttribArray(3);
				glVertexAttribDivisor(3, 1); //tous les 36 vertices

			glBindBuffer(GL_ARRAY_BUFFER, 0);

		//Déverrouillage du VAO

		glBindVertexArray(0);
	}


	TexturedCube::~TexturedCube()
	{
	}

};



Cube.h

#pragma once

#include "Shader.h"
#include "drawable.h"

#ifndef BUFFER_OFFSET

#define BUFFER_OFFSET(offset) ((char*)NULL + (offset))

#endif


namespace ARW
{
	class Cube : public ARW::Drawable
	{
	protected:
		Shader m_shader;
		float m_vertices[108];
		float m_colors[108];
		GLuint m_vboCubeID;
		GLuint m_vaoID;
		int m_verticesSize_Bytes;
		int m_colorSize_Bytes;
	public:
		Cube(float size, std::string const vertexShader, std::string const fragmentShader);
		virtual void load();
		virtual void draw(glm::mat4 &projection, glm::mat4 &modelview);		
		void updateVBO(void *donnees, int tailleBytes, int decalage);
		virtual ~Cube();
	};
};


Cube.cpp

#include "Cube.h"

namespace ARW
{
	Cube::Cube(float size, std::string const vertexShader, std::string const fragmentShader) : m_shader(vertexShader, fragmentShader), m_vaoID(0), m_vboCubeID(0), m_verticesSize_Bytes(108*sizeof(float)), m_colorSize_Bytes(108*sizeof(float))
	{
		if (!m_shader.load())
			std::cout << "Fail to load shader" << std::endl;
		size /= 2;

		float verticesTmp[] = {
			-size, -size, -size,   size, -size, -size,   size, size, -size,
			-size, -size, -size,   -size, size, -size,   size, size, -size,

			size, -size, size,   size, -size, -size,   size, size, -size,
			size, -size, size,   size, size, size,   size, size, -size,

			-size, -size, size,   size, -size, size,   size, -size, -size,
			-size, -size, size,   -size, -size, -size,   size, -size, -size,

			-size, -size, size,   size, -size, size,   size, size, size,
			-size, -size, size,   -size, size, size,   size, size, size,

			-size, -size, -size,   -size, -size, size,   -size, size, size,
			-size, -size, -size,   -size, size, -size,   -size, size, size,

			-size, size, size,   size, size, size,   size, size, -size,
			-size, size, size,   -size, size, -size,   size, size, -size };


		float colorsTmp[] = {
			1.0, 0.0, 0.0,   1.0, 0.0, 0.0,   1.0, 0.0, 0.0,           // Face 1
			1.0, 0.0, 0.0,   1.0, 0.0, 0.0,   1.0, 0.0, 0.0,           // Face 1

			0.0, 1.0, 0.0,   0.0, 1.0, 0.0,   0.0, 1.0, 0.0,           // Face 2
			0.0, 1.0, 0.0,   0.0, 1.0, 0.0,   0.0, 1.0, 0.0,           // Face 2

			0.0, 0.0, 1.0,   0.0, 0.0, 1.0,   0.0, 0.0, 1.0,           // Face 3
			0.0, 0.0, 1.0,   0.0, 0.0, 1.0,   0.0, 0.0, 1.0,           // Face 3

			1.0, 0.0, 0.0,   1.0, 0.0, 0.0,   1.0, 0.0, 0.0,           // Face 4
			1.0, 0.0, 0.0,   1.0, 0.0, 0.0,   1.0, 0.0, 0.0,           // Face 4

			0.0, 1.0, 0.0,   0.0, 1.0, 0.0,   0.0, 1.0, 0.0,           // Face 5
			0.0, 1.0, 0.0,   0.0, 1.0, 0.0,   0.0, 1.0, 0.0,           // Face 5

			0.0, 0.0, 1.0,   0.0, 0.0, 1.0,   0.0, 0.0, 1.0,           // Face 6
			0.0, 0.0, 1.0,   0.0, 0.0, 1.0,   0.0, 0.0, 1.0 };         // Face 6

		for (int i(0); i < 108; i++)
		{
			m_vertices[i] = verticesTmp[i];
			m_colors[i] = colorsTmp[i];
		}
	}

	void Cube::draw(glm::mat4 & projection, glm::mat4 & modelview)
	{

		glUseProgram(m_shader.getProgramID());

			glBindVertexArray(m_vaoID);

				glUniformMatrix4fv(glGetUniformLocation(m_shader.getProgramID(), "projection"), 1, GL_FALSE, value_ptr(projection));
				glUniformMatrix4fv(glGetUniformLocation(m_shader.getProgramID(), "modelview"), 1, GL_FALSE, value_ptr(modelview));
				
				glDrawArrays(GL_TRIANGLES, 0, 36);
			glBindVertexArray(0);

		glUseProgram(0);
	}

	void Cube::load()
	{

		if (glIsBuffer(m_vboCubeID) == GL_TRUE)
			glDeleteBuffers(1, &m_vboCubeID);
		glGenBuffers(1, &m_vboCubeID);
		

		// Verrouillage du VBO

		glBindBuffer(GL_ARRAY_BUFFER, m_vboCubeID);


		// Allocation de la mémoire vidéo

			glBufferData(GL_ARRAY_BUFFER, m_verticesSize_Bytes + m_colorSize_Bytes, 0, GL_STATIC_DRAW);


			// Transfert des données

			glBufferSubData(GL_ARRAY_BUFFER, 0, m_verticesSize_Bytes, m_vertices);
			glBufferSubData(GL_ARRAY_BUFFER, m_verticesSize_Bytes, m_colorSize_Bytes, m_colors);


		// Déverrouillage de l'objet

		glBindBuffer(GL_ARRAY_BUFFER, 0);


		if (glIsVertexArray(m_vaoID) == GL_TRUE)
			glDeleteVertexArrays(1, &m_vaoID);
		glGenVertexArrays(1, &m_vaoID);

		//Verrouillage du VAO

		glBindVertexArray(m_vaoID);

			//Verrouillage du VBO

			glBindBuffer(GL_ARRAY_BUFFER, m_vboCubeID);


			// Accès aux vertices dans la mémoire vidéo

			glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
			glEnableVertexAttribArray(0);


			// Accès aux couleurs dans la mémoire vidéo

			glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(m_verticesSize_Bytes));
			glEnableVertexAttribArray(1);


			// Déverrouillage du VBO

			glBindBuffer(GL_ARRAY_BUFFER, 0);

		//Déverrouillage du VAO

		glBindVertexArray(0);
	}

	void Cube::updateVBO(void *donnees, int tailleBytes, int decalage)
	{

		glBindBuffer(GL_ARRAY_BUFFER, m_vboCubeID);

		void *adresseVBO = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);

		if (adresseVBO == NULL)
		{
			std::cout << "Erreur au niveau de la récupération du VBO" << std::endl;
			glBindBuffer(GL_ARRAY_BUFFER, 0);

			return;
		}

		memcpy((char*)adresseVBO + decalage, donnees, tailleBytes);

		glUnmapBuffer(GL_ARRAY_BUFFER);
		adresseVBO = 0;

		glBindBuffer(GL_ARRAY_BUFFER, 0);
	}

	Cube::~Cube()
	{
		glDeleteBuffers(1, &m_vboCubeID);
		glDeleteVertexArrays(1, &m_vaoID);
	}
};

Camera.h

#pragma once
#define GLM_ENABLE_EXPERIMENTAL 1
#define GLM_FORCE_RADIANS

#include <SFML\Graphics\Image.hpp>
#include <SFML\OpenGL.hpp>
#include <glm/glm.hpp>
#include <glm/gtx/transform.hpp>
#include <glm/gtc/type_ptr.hpp>

#define M_PI 3.14159265358979323846

namespace ARW
{
	class Camera
	{
	public:
		Camera();
		Camera(glm::vec3 position, glm::vec3 targetPoint, glm::vec3 verticalAxis);
		void angle(float xRel, float yRel);
		void setTargetPoint(glm::vec3 targetPoint);
		void lookAt(glm::mat4 & modelview);
		~Camera();


	private:

		float m_xCoeff, m_yCoeff;
		int m_phi_down_limit, m_phi_upper_limit;

		float m_phi;
		float m_theta;
		glm::vec3 m_orientation;

		glm::vec3 m_verticalAxis;
		glm::vec3 m_lateralTranslation;

		glm::vec3 m_position;
		glm::vec3 m_targetPoint;
	};
};


Camera.cpp

#include "Camera.h"

namespace ARW
{

	Camera::Camera() : m_phi(0.0), m_theta(0.0), m_orientation(), m_verticalAxis(0, 0, 1), m_lateralTranslation(), m_position(), m_targetPoint(), m_xCoeff(0.5), m_yCoeff(0.5), m_phi_down_limit(-1.55334303427), m_phi_upper_limit(1.55334303427)
	{
	}

	Camera::Camera(glm::vec3 position, glm::vec3 targetPoint, glm::vec3 verticalAxis) : m_phi(-0.61540309425), m_theta(-2.35619449019), m_orientation(), m_verticalAxis(verticalAxis), m_lateralTranslation(), m_position(position), m_targetPoint(targetPoint), m_xCoeff(0.5), m_yCoeff(0.5), m_phi_down_limit(-1.55334303427), m_phi_upper_limit(1.55334303427)
	{
	}

	void Camera::angle(float xRel, float yRel)
	{
		m_phi += -yRel * m_xCoeff;
		m_theta += -xRel * m_yCoeff;

		if (m_verticalAxis.y == 1.0)
		{
			m_orientation.x = cos(m_phi) * sin(m_theta);
			m_orientation.y = sin(m_phi);
			m_orientation.z = cos(m_phi) * cos(m_theta);
		}		

		else if (m_verticalAxis.x == 1.0)
		{
			m_orientation.x = sin(m_phi);
			m_orientation.y = cos(m_phi) * cos(m_theta);
			m_orientation.z = cos(m_phi) * sin(m_theta);
		}

		else
		{
			m_orientation.x = cos(m_phi) * cos(m_theta);
			m_orientation.y = cos(m_phi) * sin(m_theta);
			m_orientation.z = sin(m_phi);
		}
		m_lateralTranslation = cross(m_verticalAxis, m_orientation);
		m_lateralTranslation = normalize(m_lateralTranslation);

		m_targetPoint = m_position + m_orientation;
	}

	void Camera::setTargetPoint(glm::vec3 targetPoint)
	{

		m_orientation = m_targetPoint - m_position;
		m_orientation = normalize(m_orientation);

		if (m_verticalAxis.y == 1.0)
		{
			m_phi = asin(m_orientation.y);
			m_theta = acos(m_orientation.z / cos(m_phi));

			if (m_orientation.z < 0)
				m_theta *= -1;
		}		

		else if (m_verticalAxis.x == 1.0)
		{
			m_phi = asin(m_orientation.x);
			m_theta = acos(m_orientation.y / cos(m_phi));

			if (m_orientation.y < 0)
				m_theta *= -1;
		}

		else
		{
			m_phi = asin(m_orientation.x);
			m_theta = acos(m_orientation.z / cos(m_phi));

			if (m_orientation.z < 0)
				m_theta *= -1;
		}
	}

	void Camera::lookAt(glm::mat4 &modelview)
	{
		modelview = glm::lookAt(m_position, m_targetPoint, m_verticalAxis);
	}

	Camera::~Camera()
	{
	}

};


OpenGLScene.h

#pragma once

#define GLM_ENABLE_EXPERIMENTAL 1

#include <GL\glew.h>
#include <SFML\Graphics.hpp>
#include <SFML\OpenGL.hpp>
#include <glm/glm.hpp>
#include <glm/gtx/transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <iostream>

#include "drawable.h"
#include "Camera.h"
#include "TexturedCube.h"

namespace ARW
{
	class OpenGLScene
	{
	private:
		glm::mat4  m_modelview;
		glm::mat4 m_projection;
		ARW::Camera c;
		std::vector<ARW::Drawable*> drawables;
	public:
		OpenGLScene();
		bool load(double pov, double res);
		Camera * getCamera();
		void show();
		~OpenGLScene();
	};
};

OpenGLScene.cpp

#include "OpenGLScene.h"

namespace ARW
{

	OpenGLScene::OpenGLScene()
	{
	}

	bool OpenGLScene::load(double pov, double res)
	{
		
		glewExperimental = true;

		if (glewInit() != GLEW_OK) {
			std::cout << "Failed to initialize GLEW" << std::endl;
			return EXIT_FAILURE;
		}
		glEnable(GL_DEPTH_TEST);


		m_projection = glm::perspective(pov, res, 1.0, 100.0);
		m_modelview = glm::mat4(1.0);
		c = Camera(glm::vec3(5.0, 5.0, 5.0), glm::vec3(0.0, 0.0, 0.0), glm::vec3(0.0, 1.0, 0.0));

		TexturedCube * t = new TexturedCube(1.0, "texture.vert", "texture.frag", "text.jpg");
		t->load();
		drawables.push_back(t);

		return EXIT_SUCCESS;
	}

	void OpenGLScene::show()
	{
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);		
		c.lookAt(m_modelview);
		drawables[0]->draw(m_projection, m_modelview);
		
	}

	Camera * OpenGLScene::getCamera()
	{
		return &c;
	}

	OpenGLScene::~OpenGLScene()
	{
	}

};

main.cpp

#define GLM_ENABLE_EXPERIMENTAL 1

#include <GL\glew.h>
#include <SFML\Graphics.hpp>
#include <SFML\OpenGL.hpp>
#include <iostream>
#include <glm/glm.hpp>
#include <glm/gtx/transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "Shader.h"
#include "Cube.h"
#include "OpenGLScene.h"


using namespace glm;

int main()
{
	sf::ContextSettings settings;
	settings.depthBits = 24;
	settings.stencilBits = 8;
	settings.antialiasingLevel = 4;
	settings.majorVersion = 3;
	settings.minorVersion = 3;


	sf::Window window(sf::VideoMode(1600, 900), "OpenGL", sf::Style::Default, settings);//doit être déclaré avant glewExperimental

	ARW::OpenGLScene sc;

	sc.load(70.0, (double)16 / 9);

	while (window.isOpen())
	{
		sf::Event Event;
		while (window.pollEvent(Event))
		{
			if (Event.type == sf::Event::Closed)
				window.close();

			if ((Event.type == sf::Event::KeyPressed) && (Event.key.code == sf::Keyboard::Escape))
				window.close();

		}
		
		sc.show();

		window.display();
	
	}
	return EXIT_SUCCESS;
}


Comme j'ai une seule classe shader et qu'elle spécifie quels sont les numéros pour vertex couleur texture etc je pense que je ne peux pas mettre les textures en 1 par exemple quand je le veux. Ça marcherait bien si je pouvais le gérer indépendamment dans le shader mais bon... Pour le tableau temporaire de texture je n'ai pas vraiment le choix. 












-
Edité par Gypso2 15 octobre 2018 à 12:24:29

  • Partager sur Facebook
  • Partager sur Twitter
15 octobre 2018 à 16:34:00

Hello.

Ton code est inutilement compliqué je pense. Je m'explique : ton but c'est de tester l'instancing. Pourquoi veux tu afficher un cube texturé. Contente toi d'afficher un cube coloré le code ce sera moins compliqué et vu qu'il y aura probablement moins de code, plus simple à debugger (remarque à ne pas prendre méchanmment, mais vu que tu cherches à tester une features, isole là au maximum :) ).

Ensuite rien que le fait que d'utiliser gl_InstanceID ne fonctionne pas, c'est qu'il y a un problème en amont à mon avis. Je n'ai pas vu d'erreur grossière à côté en tout cas, après j'ai pas testé.

Je t'encourage déjà de cleaner ton code un maximum pour pouvoir tester uniquement la partie instantiation.

Ensuite, vu qu'on est sur le forum de C++, je me permet de te faire des remarques :

En C++ on utilise pas delete, ni new (enfin pour new c'est à prendre avec des pincettes, mais étant donné que tu me sembles être débutant, considère new comme interdit sauf dans les bibliothèques où il y a une gestion de la mémoire à la parent enfant à l'instar de Qt. On utilise des pointeurs intelligents.

En C++ on utilise pas malloc ou autre joyeuseté pour les tableaux dynamique. On utilise std::vector.

En C++ on utilise pas de tableau statique à la C. On utilise std::array.

Ensuite sur ta partie organisation de code. Tu sembles attaché une importance particulière à glBindAttribLocation. Lorsque tu vas faire des vrais shaders : tone mapper, gestion des lumières, et autres, tu comptes toujours avoir les même variables? Non, il faut que tu te sépares de ton approche et te forcer à utiliser layout(location) comme spécifié plus haut (btw, c'est l'approche hautement recommandé pour Vulkan).

Tu devrais développer une classe pour la gestion de tes buffers. Car là tu fais du copier coller en boucle c'est pas bon.

Tu n'as pas forcément besoin de sélectionner le buffer "0" comme tu le fais régulièrement. 

Tu essaies de penser à la gestion des erreurs (pointeur null etc) c'est une très bonne chose ! Par contre tu le fais mal et tu risques d'avoir des fuites mémoires avec ta façon de faire.

Tu fais un héritage entre TexturedCube et Cube. C'est pas une mauvaise approche en sois étant donné que TexturedCube IS A Cube. En revenche j'aurais préféré une relation de type Cube avec une texture, ça t'aurait évité de recopier du code en masse.

On utilise pas 0 ou NULL en C++, mais nullptr.

Voilà, pour revenir à ton problème, avant de passer par un VBO / UBO de translation, je t'encourage à tester POURQUOI la version avec gl_InstanceID ne fonctionne pas. Ce n'est pas normal. Es tu sûre que c'est bien ce shader là qui est pris en compte? (si tu enlèves un ";" et que ça marche toujours, poses toi des questions ;) ).

Simplifie également ton shader pour la 52ème fois : tu te sers pas des couleurs (ou pas des textures avec ma remarque ci dessus), enlève donc les parties qui ne sont pas intéressantes pour toi.

Voilà voilà, bon courage...

PS : tu peux peut être utiliser renderdoc pour voir ce qu'il se passe étape par étape ;)

  • Partager sur Facebook
  • Partager sur Twitter
http://cpp-rendering.io : Vous trouverez tout ce dont vous avez besoin sur Vulkan / OpenGL et le rendu 3D !
15 octobre 2018 à 18:41:31

Pour le code, c'est juste un c/c du tuto présent sur ce site, étant donné que je cherche à voir comment marche opengl je n'y ai pas touché (ou pas bcp). Je ne me force pas à utiliser glBindAttribLocation c'est juste que ça ne marchait pas avec les layout(location), mais du coup oui il y a bien un problème au niveau de la classe shader car il n'est pas pris en compte... Je vais regarder ça de plus près, en revanche il est probable que je ne fasse pas d'apparition sur le post pendant un petit moment. Merci bcp. 

EDIT : Me revoilà plus tôt que prévu, en fait c'était un problème de version de shader : il faut minimum la version 330. Du coup je vais essayer de faire un petit truc propre avec ce que tu m'as dit. Merci beaucoup :)

-
Edité par Gypso2 16 octobre 2018 à 11:03:33

  • Partager sur Facebook
  • Partager sur Twitter