[Problem]ogl-sample-410 + brick shader

hi,all
I’m reading the Orange Book(3rdE), and trying to integrate the brick shader into g-truc’s ogl-sample-410 framework , but fail.
When I lanuch the application, the window is full filled with orange color, the brick texture is not rendered at all.
Could you give me any clues on this problem? Thank you.
My code is listed here, and the files is also attached.

P.S. I have already updated my GeforceGTX460 to the lastest driver, which supports OpenGL4.1.

------------------CH06-brick.vert---------------------

//#version 140
#version 400 core

in vec4 MCvertex;
in vec3 MCnormal;

uniform mat4 MVMatrix;
uniform mat4 MVPMatrix;
uniform mat3 NormalMatrix;
const vec3 LightPosition = vec3(0.0, 0.0, 4.0);//uniform vec3 LightPosition;

const float SpecularContribution = 0.3;
const float DiffuseContribution = 1.0 - SpecularContribution;

out float LightIntensity;
out vec2 MCposition;

void main()
{
	vec3 ecPosition = vec3(MVMatrix * MCvertex);
	vec3 tnorm = normalize(NormalMatrix * MCnormal);
	vec3 lightVec = normalize(LightPosition - ecPosition);
	vec3 reflectVec = reflect(-lightVec, tnorm);
	vec3 viewVec = normalize(-ecPosition);
	float diffuse = max(dot(lightVec, tnorm), 0.0);
	
	float spec = 0.0;
	if (diffuse > 0.0)
	{
		spec = max(dot(reflectVec, viewVec), 0.0);
		spec = pow(spec, 16.0);
	}
	LightIntensity = DiffuseContribution * diffuse +
		SpecularContribution * spec;

	MCposition = MCvertex.xy;
	gl_Position = MVPMatrix * MCvertex;

}

------------------CH06-brick.frag---------------------

//#version 140
#version 400 core

// uniform vec3 BrickColor;
// uniform vec3 MortarColor;
// uniform vec2 BrickSize;
// uniform vec2 BrickPct;
const vec3 BrickColor = vec3(1.0, 0.3, 0.2);
const vec3 MortarColor = vec3(0.85, 0.86, 0.84);
const vec2 BrickSize = vec2(0.30, 0.15);
const vec2 BrickPct = vec2(0.90, 0.85);

uniform sampler2D Diffuse;

in float LightIntensity;
in vec2 MCposition;

out vec4 FragColor;


void main()
{
	vec3 color;
	vec2 position, useBrick;
	position = MCposition / BrickSize;
	if (fract(position.y * 0.5) > 0.5)
		position.x += 0.5;
	position = fract(position);
	useBrick = step(position, BrickPct);
	//
	color = mix(MortarColor, BrickColor, useBrick.x * useBrick.y);
	color *= LightIntensity;
	FragColor = vec4(color, 1.0);
}

------------------cpp---------------------

#include <glf/glf.hpp>
#include <glm/gtx/inverse_transpose.hpp>

namespace
{
	std::string const SAMPLE_NAME = "OpenGL Programmable trilinear filtering";
	std::string const VERTEX_SHADER_SOURCE(glf::DATA_DIRECTORY + "410/CH06-brick.vert");
	std::string const FRAGMENT_SHADER_SOURCE(glf::DATA_DIRECTORY + "410/CH06-brick.frag");
 	std::string const TEXTURE_DIFFUSE_DXT5(glf::DATA_DIRECTORY + "kueken256-dxt5.dds");
	int const SAMPLE_SIZE_WIDTH = 640;
	int const SAMPLE_SIZE_HEIGHT = 480;
	int const SAMPLE_MAJOR_VERSION = 4;
	int const SAMPLE_MINOR_VERSION = 1;

	struct vertex
	{
		vertex
		(
			glm::vec2 const & Position,
			glm::vec2 const & Texcoord
		) :
			Position(Position),
			Texcoord(Texcoord)
		{}

		glm::vec2 Position;
		glm::vec2 Texcoord;
	};

	GLsizei const VertexCount = 4;
	GLsizeiptr const VertexSize = VertexCount * sizeof(glf::vertex_v2fv2f);
	glf::vertex_v2fv2f const VertexData[VertexCount] =
	{
		glf::vertex_v2fv2f(glm::vec2(-1.0f,-1.0f), glm::vec2(0.0f, 1.0f)),
		glf::vertex_v2fv2f(glm::vec2( 1.0f,-1.0f), glm::vec2(1.0f, 1.0f)),
		glf::vertex_v2fv2f(glm::vec2( 1.0f, 1.0f), glm::vec2(1.0f, 0.0f)),
		glf::vertex_v2fv2f(glm::vec2(-1.0f, 1.0f), glm::vec2(0.0f, 0.0f))
	};

	GLsizei const ElementCount = 6;
	GLsizeiptr const ElementSize = ElementCount * sizeof(GLushort);
	GLushort const ElementData[ElementCount] =
	{
		0, 1, 2, 
		2, 3, 0
	};

	glf::window Window(glm::ivec2(SAMPLE_SIZE_WIDTH, SAMPLE_SIZE_HEIGHT));

	namespace buffer
	{
		enum type
		{
			VERTEX,
			ELEMENT,
			MAX
		};
	}//namespace buffer

	GLuint VertexArrayName(0);
	GLuint PipelineName(0);
	GLuint ProgramName(0);

	GLuint BufferName[buffer::MAX] = {0, 0};
	GLuint Image2DName(0);
	GLuint SamplerName(0);

	GLuint UniformMVP(0);
	GLuint UniformMV(0);
	GLuint UniformNormalMatrix(0);
	GLuint UniformDiffuse(0);
//	GLuint UniformLightPosition(0);
}//namespace

bool initProgram()
{
	bool Validated = true;

	glGenProgramPipelines(1, &PipelineName);
	glBindProgramPipeline(PipelineName);
	glBindProgramPipeline(0);

	if(Validated)
	{
		GLuint VertexShaderName = glf::createShader(GL_VERTEX_SHADER, VERTEX_SHADER_SOURCE);
		GLuint FragmentShaderName = glf::createShader(GL_FRAGMENT_SHADER, FRAGMENT_SHADER_SOURCE);

		ProgramName = glCreateProgram();
		glProgramParameteri(ProgramName, GL_PROGRAM_SEPARABLE, GL_TRUE);
		glAttachShader(ProgramName, VertexShaderName);
		glAttachShader(ProgramName, FragmentShaderName);
		glDeleteShader(VertexShaderName);
		glDeleteShader(FragmentShaderName);
		glLinkProgram(ProgramName);
		Validated = glf::checkProgram(ProgramName);
	}

	if(Validated)
	{
		glUseProgramStages(PipelineName, GL_FRAGMENT_SHADER_BIT | GL_VERTEX_SHADER_BIT, ProgramName);
		Validated = Validated && glf::checkError("initProgram - stage");
	}

	if(Validated)
	{
		UniformMVP = glGetUniformLocation(ProgramName, "MVPMatrix");
		UniformMV  = glGetUniformLocation(ProgramName, "MVMatrix");
		UniformNormalMatrix   = glGetUniformLocation(ProgramName, "NormalMatrix");
		UniformDiffuse = glGetUniformLocation(ProgramName, "Diffuse");
//		UniformLightPosition = glGetUniformLocation(ProgramName, "LightPosition");
	}

	return glf::checkError("initProgram");
}

bool initArrayBuffer()
{
	glGenBuffers(buffer::MAX, BufferName);
	glNamedBufferDataEXT(BufferName[buffer::VERTEX], VertexSize, VertexData, GL_STATIC_DRAW);
	glNamedBufferDataEXT(BufferName[buffer::ELEMENT], ElementSize, ElementData, GL_STATIC_DRAW);

	return glf::checkError("initArrayBuffer");;
}

bool initTexture2D()
{
	glGenTextures(1, &Image2DName);

	glTextureParameteriEXT(Image2DName, GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
	glTextureParameteriEXT(Image2DName, GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1000);
	glTextureParameteriEXT(Image2DName, GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_RED);
	glTextureParameteriEXT(Image2DName, GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_GREEN);
	glTextureParameteriEXT(Image2DName, GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_BLUE);
	glTextureParameteriEXT(Image2DName, GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_ALPHA);

	gli::texture2D Image = gli::load(TEXTURE_DIFFUSE_DXT5);
	for(std::size_t Level = 0; Level < Image.levels(); ++Level)
	{
		glCompressedTextureImage2DEXT(
			Image2DName,
			GL_TEXTURE_2D,
			GLint(Level),
			GL_COMPRESSED_RGBA_S3TC_DXT5_EXT,
			GLsizei(Image[Level].dimensions().x), 
			GLsizei(Image[Level].dimensions().y), 
			0, 
			GLsizei(Image[Level].capacity()), 
			Image[Level].data());
	}

	return glf::checkError("initTexture2D");
}

bool initVertexArray()
{
	glGenVertexArrays(1, &VertexArrayName);

	glVertexArrayVertexAttribOffsetEXT(VertexArrayName, BufferName[buffer::VERTEX], 
		glf::semantic::attr::POSITION, 2, GL_FLOAT, GL_FALSE, sizeof(vertex), 0);
	glVertexArrayVertexAttribOffsetEXT(VertexArrayName, BufferName[buffer::VERTEX], 
		glf::semantic::attr::TEXCOORD, 2, GL_FLOAT, GL_FALSE, sizeof(vertex), sizeof(glm::vec2));

	glEnableVertexArrayAttribEXT(VertexArrayName, glf::semantic::attr::POSITION);
	glEnableVertexArrayAttribEXT(VertexArrayName, glf::semantic::attr::TEXCOORD);

	return glf::checkError("initVertexArray");
}

bool begin()
{
	bool Validated = true;
	Validated = Validated && glf::checkGLVersion(SAMPLE_MAJOR_VERSION, SAMPLE_MINOR_VERSION);
	Validated = Validated && glf::checkExtension("GL_EXT_direct_state_access");

	if(Validated)
		Validated = initProgram();
	if(Validated)
		Validated = initArrayBuffer();
	if(Validated)
		Validated = initTexture2D();
	if(Validated)
		Validated = initVertexArray();

	return Validated && glf::checkError("begin");
}

bool end()
{
	glDeleteBuffers(buffer::MAX, BufferName);
	glDeleteProgram(ProgramName);
	glDeleteTextures(1, &Image2DName);
	glDeleteSamplers(1, &SamplerName);
	glDeleteVertexArrays(1, &VertexArrayName);
	glDeleteProgramPipelines(1, &PipelineName);

	return glf::checkError("end");
}

void display()
{
	// Compute the MVP (Model View Projection matrix)
	glm::mat4 Projection = glm::perspective(45.0f, 4.0f / 3.0f, 0.1f, 1000.0f);
	glm::mat4 ViewTranslate = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -Window.TranlationCurrent.y));
	glm::mat4 ViewRotateX = glm::rotate(ViewTranslate, Window.RotationCurrent.y, glm::vec3(1.f, 0.f, 0.f));
	glm::mat4 View = glm::rotate(ViewRotateX, Window.RotationCurrent.x, glm::vec3(0.f, 1.f, 0.f));
	glm::mat4 Model = glm::mat4(1.0f);
	glm::mat4 MVP = Projection * View * Model;
	glm::mat4 MV  = View * Model;
	glm::mat3 NormalMatrix = glm::inverseTranspose(glm::mat3(MV));
//	glm::vec3 LightPosition = glm::vec3(0.0, 0.0, 4.0);

	glProgramUniformMatrix4fv(ProgramName, UniformMVP, 1, GL_FALSE, &MVP[0][0]);
	glProgramUniformMatrix4fv(ProgramName, UniformMV, 1, GL_FALSE, &MV[0][0]);
	glProgramUniformMatrix3fv(ProgramName, UniformNormalMatrix, 1, GL_FALSE, &NormalMatrix[0][0]);
//	glProgramUniform1fv(ProgramName, UniformLightPosition, 1, &LightPosition[0]);
	glProgramUniform1i(ProgramName, UniformDiffuse, 0);

	glViewportIndexedf(0, 0, 0, float(Window.Size.x), float(Window.Size.y));
	glClearBufferfv(GL_COLOR, 0, &glm::vec4(1.0f, 0.5f, 0.0f, 1.0f)[0]);

	glViewportIndexedf(0, 0, 0, float(Window.Size.x), float(Window.Size.y));

	glBindProgramPipeline(PipelineName);
	glBindMultiTextureEXT(GL_TEXTURE0, GL_TEXTURE_2D, Image2DName);
	glBindVertexArray(VertexArrayName);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, BufferName[buffer::ELEMENT]);
	glDrawElementsInstancedBaseVertex(GL_TRIANGLES, ElementCount, GL_UNSIGNED_SHORT, NULL, 1, 0);

	glf::checkError("display");
	glf::swapBuffers();
}

int main(int argc, char* argv[])
{
	if(glf::run(
		argc, argv,
		glm::ivec2(SAMPLE_SIZE_WIDTH, SAMPLE_SIZE_HEIGHT), 
		SAMPLE_MAJOR_VERSION, 
		SAMPLE_MINOR_VERSION))
		return 0;
	return 1;
}

One problem I see is that you need to set a location to:

in vec4 MCvertex;
in vec3 MCnormal;

Replace by:

// Declare all the semantics
#define ATTR_POSITION	0
#define ATTR_COLOR	3
#define ATTR_TEXCOORD	4

layout(location = ATTR_POSITION) in vec4 MCvertex;
layout(location = ATTR_NORMAL) in vec3 MCnormal;

Also, the data defines in the C++ file doesn’t match your vertex array:

glVertexArrayVertexAttribOffsetEXT(VertexArrayName, BufferName[buffer::VERTEX], glf::semantic::attr::POSITION, 2, GL_FLOAT, GL_FALSE, sizeof(vertex), 0);
glVertexArrayVertexAttribOffsetEXT(VertexArrayName, BufferName[buffer::VERTEX], glf::semantic::attr::TEXCOORD, 2, GL_FLOAT, GL_FALSE, sizeof(vertex), sizeof(glm::vec2));

Thanks for your reply,Groovounet.
But where is the ATTR_NORMAL come from?

and how to correct the following code?

glVertexArrayVertexAttribOffsetEXT(VertexArrayName, BufferName[buffer::VERTEX], glf::semantic::attr::TEXCOORD, 2, GL_FLOAT, GL_FALSE, sizeof(vertex), sizeof(glm::vec2));

It seems that glf::semantic doesn’t define attr::NORMAL, Should I use glf::semantic::attr::POSITION instead?

True!

Then define it. It comes out of nowhere, they are arbitrary. A computer like numbers and in the end all that matter it that in the GLSL shader and in the C++ program, the same location (a number) is used. We are human and numbers don’t work that well for us that’ why I use “semantic” through enum (C++ side) and define (GLSL side) to hide the locations.

True!

Then define it. It comes out of nowhere, they are arbitrary. A computer like numbers and in the end all that matter it that in the GLSL shader and in the C++ program, the same location (a number) is used. We are human and numbers don’t work that well for us that’ why I use “semantic” through enum (C++ side) and define (GLSL side) to hide the locations.