Help with shader error

I’m receiving a shader errors:
0(15) : error C1321: structure type ‘lightType’ may not be defined in a uniform or buffer block

Heres what the part is:

layout(std140, binding = 1) uniform lightArray {
	struct lightType {
		vec4 position;
		vec4 color;
	} light[100];
} LightArray;

This part I’m receiving error: 0(8) : error C0000: syntax error, unexpected type identifier, expecting ‘{’ at token “vec4”
0(10) : error C0000: syntax error, unexpected ‘}’ at token “}”
It looks allright to me, what’s wrong?

gl_Position = LightTransform.VPMatrix[gl_InvocationID] * vec4(outVertexPosition[i], 1.f);

Heres the whole shader:

#version 420 core

layout(std140, binding = 2) uniform lightTransform {
	mat4 VPMatrix[600];
} LightTransform;

layout(std140, binding = 1) uniform lightArray {
	struct lightType {
		vec4 position;
		vec4 color;
	} light[100];
} LightArray;

layout(triangles, invocations = 10) in;
layout(triangle_strip, max_vertices = 3) out;

layout(location = 0) in vec3 outVertexPosition[];

out gl_PerVertex {
	vec4 gl_Position;
};

void main() {

	vec3 normal = cross(outVertexPosition[2]-outVertexPosition[0], outVertexPosition[0]-outVertexPosition[1]);
	vec3 light = vec3(LightArray.light[gl_InvocationID].position) - outVertexPosition[0];
	
	if (dot(normal, light) > 0.f) {

		for (int i=0; i<3; ++i) {
			gl_Position = LightTransform.VPMatrix[gl_InvocationID] * vec4(outVertexPosition[i], 1.f);
			gl_Layer = gl_InvocationID;
			EmitVertex();
		}
		EndPrimitive();

	}
}

It comes from a book “opengl insights”

Thank you.

I moved the struct outside to this and it compiles the application runs.

struct lightType {
		vec4 position;
		vec4 color;
	};

layout(std140, binding = 1) uniform lightArray {
	lightType light[100];
} LightArray;

This is what I get, supposed to be multiple shadows:

Any idea what the problem is?

I have changed the shader code and updated the application code too:


layout(std140, binding = 1) uniform lightPosArray {
	vec4 lightPos[100];
} LightPosArray;

layout(std140, binding = 1) uniform lightColorArray {
	vec4 lightColor[100];
} LightColorArray;

The result is similar to the picture in previous post, any ideas?

I know it’s a lot but I’m posting the scene code, can you tell anything wrong?

/*
 * dragon.cpp
 *
 *  Created on: Sep 24, 2011
 *      Author: aqnuep
 */

#include <iostream>
#include <fstream>
#define GLEW_STATIC
#include <GL/glew.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <glm/glm.hpp>
#include <glm/gtx/matrix_operation.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include "wavefront.h"
#include "tga.h"
#include "dragon.h"
#define M_PI 3.14
#define CHECK_GL_ERROR()												\
{																		\
	GLenum glError;														\
	if ((glError = glGetError()) != GL_NO_ERROR) {						\
		cerr << "OpenGL error code in '" << __FILE__ << "' at line " << __LINE__ << ": " << gluErrorString(glError) << endl;	\
	}																	\
}

#define CHECK_FRAMEBUFFER_STATUS()                            \
{                                                             \
    GLenum status;                                            \
    status = glCheckFramebufferStatus(GL_FRAMEBUFFER);		  \
    switch(status) {                                          \
    case GL_FRAMEBUFFER_COMPLETE:                         	  \
        break;                                                \
    case GL_FRAMEBUFFER_UNSUPPORTED:                    	  \
        /* choose different formats */                        \
        cerr << "Unsupported framebuffer format!" << endl;	  \
        break;                                                \
    case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:				  \
    	cerr << "Incomplete framebuffer attachment!" << endl; \
    	break;												  \
    case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:		  \
    	cerr << "Missing framebuffer attachment!" << endl; 	  \
    	break;												  \
    case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS:			  \
    	cerr << "Incomplete layer target!" << endl;			  \
    	break;												  \
    default:                                                  \
        /* programming error; will fail on all hardware */    \
        cerr << "Invalid framebuffer format!" << endl;		  \
        exit(0);                                          	  \
    }														  \
}

using namespace glm;
using namespace demo;

namespace dragon {

	DragonDemo::DragonDemo() {

		cerr << "> Initializing scene data..." << endl;

		// initialize camera data
		float aspectRatio = SCREEN_WIDTH / SCREEN_HEIGHT;
		float fieldOfView = 45.f;
		camera.position = vec3(-7.5f, 5.5f, 7.5f);
		camera.rotation = vec3(40.0f, 45.0f, 0.0f);
		transform.zNear = 0.1f;
		transform.zFar = 40.f;
		transform.nearTop = transform.zNear * tan(0.5f * fieldOfView);
		transform.nearRight = transform.nearTop * aspectRatio;
		transform.Viewport = vec4(0.f, 0.f, SCREEN_WIDTH, SCREEN_HEIGHT);
		transform.ProjectionMatrix = perspective(fieldOfView, aspectRatio, transform.zNear, transform.zFar);

		// create uniform buffer and store camera data
		glGenBuffers(1, &transformUB);
		glBindBuffer(GL_UNIFORM_BUFFER, transformUB);
		glBufferData(GL_UNIFORM_BUFFER, sizeof(transform), &transform, GL_STATIC_DRAW);
		glBindBufferBase(GL_UNIFORM_BUFFER, 0, transformUB);

		loadShaders();
		loadModels();
		setupGBuffer();
		createLights();

		glEnable(GL_FRAMEBUFFER_SRGB);

		cerr << "> Configuring rendering environment..." << endl;

		glEnable(GL_CULL_FACE);

		cerr << "> Done!" << endl;

		CHECK_GL_ERROR();
	}

	DragonDemo::~DragonDemo() {

		cerr << "> Freeing graphics resources... ";

		// delete shader programs
		glDeleteProgram(GBufferVSP);
		glDeleteProgram(GBufferFSP);
		glDeleteProgram(shadowMultiVSP);
		glDeleteProgram(shadowMultiGSP);
		glDeleteProgram(shadowSingleVSP);
		glDeleteProgram(lightVSP);
		glDeleteProgram(lightGSP);
		glDeleteProgram(lightFSP);

		// delete program pipelines
		glDeleteProgramPipelines(1, &GBufferPPL);
		glDeleteProgramPipelines(1, &shadowMultiPPL);
		glDeleteProgramPipelines(1, &shadowSinglePPL);
		glDeleteProgramPipelines(1, &lightPPL);

		// delete uniform buffers
		glDeleteBuffers(1, &transformUB);
		glDeleteBuffers(1, &lightTransformUB);
		glDeleteBuffers(1, &lightPosUB);
		glDeleteBuffers(1, &lightColorUB);

		// delete vertex buffer
		glDeleteBuffers(1, &vertexBuffer);

		// delete index buffer
		glDeleteBuffers(1, &indexBuffer);

		// delete vertex arrays
		glDeleteVertexArrays(1, &vertexArray);

		// delete G-buffer textures
		glDeleteTextures(1, &positionGBT);
		glDeleteTextures(1, &normalGBT);
		glDeleteTextures(1, &depthGBT);

		// delete shadow map
		glDeleteTextures(1, &shadowArrayTex);

		// delete framebuffers
		glDeleteFramebuffers(1, &shadowFB);

		cerr << "Done!" << endl;

	}

	void DragonDemo::loadModels() {

		cerr << "> Loading models..." << endl;

		WaveFrontObj dragonObj("models/dragon.obj");

		cerr << "> Uploading mesh data to GPU..." << endl;

		// create empty index buffer
		int indexBufferSize = dragonObj.index.size() * sizeof(uint);
		glGenBuffers(1, &indexBuffer);
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
		glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexBufferSize, NULL, GL_STATIC_DRAW);

		// map index buffer and fill with data
		uint *index = (uint*)glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, 0, indexBufferSize,
			GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT);

		for (uint i = 0; i < dragonObj.index.size(); ++i)
			index[i] = dragonObj.index[i];

		glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);

		// create empty vertex buffer
		int vertexBufferSize = dragonObj.vertex.size() * sizeof(Vertex);
		glGenBuffers(1, &vertexBuffer);
		glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
		glBufferData(GL_ARRAY_BUFFER, vertexBufferSize, NULL, GL_STATIC_DRAW);

		// map vertex buffer and fill with data
		Vertex *vertex = (Vertex*)glMapBufferRange(GL_ARRAY_BUFFER, 0, vertexBufferSize,
			GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT);

		for (uint i = 0; i < dragonObj.vertex.size(); ++i) {
			vertex[i].position[0] = dragonObj.vertex[i].x;
			vertex[i].position[1] = dragonObj.vertex[i].y;
			vertex[i].position[2] = dragonObj.vertex[i].z;
			vertex[i].normal[0] = dragonObj.normal[i].x;
			vertex[i].normal[1] = dragonObj.normal[i].y;
			vertex[i].normal[2] = dragonObj.normal[i].z;
		}

		glUnmapBuffer(GL_ARRAY_BUFFER);

		// setup vertex array
		glGenVertexArrays(1, &vertexArray);
		glBindVertexArray(vertexArray);
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
		glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
		glEnableVertexAttribArray(0);
		glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, position));
		glEnableVertexAttribArray(1);
		glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, normal));
		glBindVertexArray(0);

		// setup draw command
		drawCommand.prim_type = GL_TRIANGLES;
		drawCommand.indexOffset = 0;
		drawCommand.indexCount = dragonObj.index.size();

		CHECK_GL_ERROR();

	}

	void DragonDemo::updateLights() {

		// update light positions and view-projection matrices
		mat4 ProjMat = perspective(90.f, (float)SCREEN_WIDTH / (float)SCREEN_HEIGHT, 0.01f, 40.f);
		for (int i = 0; i < NUMBER_OF_LIGHTS; ++i) {
			float angle = (float)i / NUMBER_OF_LIGHTS + lightRotationFactor;
			lightPos[i] = vec4(sin(angle * M_PI * 2.f) * 4.f, -2.5f,
				cos(angle * M_PI * 2.f) * 4.f, 1.f);
			lightTransform[i].VPMatrix = ProjMat * translate(rotate(rotate(mat4(1.f), +30.f, vec3(1.f, 0.f, 0.f)), angle * -360.f, vec3(0.f, 1.f, 0.f)), -vec3(lightPos[i]));
		}

		// update light uniform buffer
		glBindBuffer(GL_UNIFORM_BUFFER, lightPosUB);
		glBufferSubData(GL_UNIFORM_BUFFER, 0, NUMBER_OF_LIGHTS * sizeof(vec4), lightPos);

		glBindBuffer(GL_UNIFORM_BUFFER, lightColorUB);
		glBufferSubData(GL_UNIFORM_BUFFER, 0, NUMBER_OF_LIGHTS * sizeof(vec4), lightColor);


		// update shadow rendering VP matrix uniform buffer
		glBindBuffer(GL_UNIFORM_BUFFER, lightTransformUB);
		glBufferSubData(GL_UNIFORM_BUFFER, 0, NUMBER_OF_LIGHTS * sizeof(LightTransform), lightTransform);

	}

	void DragonDemo::createLights() {

		cerr << "> Creating lights..." << endl;

		// generate lights
		for (int i = 0; i < NUMBER_OF_LIGHTS; ++i) {
			lightColor[i] = vec4((rand() * 0.2f) / RAND_MAX + 0.1f,
				(rand() * 0.2f) / RAND_MAX + 0.1f,
				(rand() * 0.2f) / RAND_MAX + 0.1f, 1.f);

			lightPos[i] = vec4(0.0f, 0.0f, 0.0f, 1.f);
		}

		// create light uniform buffer
		glGenBuffers(1, &lightPosUB);
		glBindBuffer(GL_UNIFORM_BUFFER, lightPosUB);
		glBufferData(GL_UNIFORM_BUFFER, NUMBER_OF_LIGHTS * sizeof(vec4), lightPos, GL_STATIC_DRAW);
		glBindBufferBase(GL_UNIFORM_BUFFER, 1, lightPosUB);

		glGenBuffers(1, &lightColorUB);
		glBindBuffer(GL_UNIFORM_BUFFER, lightColorUB);
		glBufferData(GL_UNIFORM_BUFFER, NUMBER_OF_LIGHTS * sizeof(vec4), lightColor, GL_STATIC_DRAW);
		glBindBufferBase(GL_UNIFORM_BUFFER, 1, lightColorUB);

		// create shadow rendering VP matrix uniform buffer
		glGenBuffers(1, &lightTransformUB);
		glBindBuffer(GL_UNIFORM_BUFFER, lightTransformUB);
		glBufferData(GL_UNIFORM_BUFFER, NUMBER_OF_LIGHTS * sizeof(LightTransform), lightTransform, GL_STATIC_DRAW);
		glBindBufferBase(GL_UNIFORM_BUFFER, 2, lightTransformUB);

		// update light information
		lightRotationFactor = 0.f;
		updateLights();

		// create shadow map texture cube array
		glGenTextures(1, &shadowArrayTex);
		glBindTexture(GL_TEXTURE_2D_ARRAY, shadowArrayTex);
		glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_DEPTH_COMPONENT16,
			SHADOW_MAP_SIZE, SHADOW_MAP_SIZE, NUMBER_OF_LIGHTS,
			0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);

		// create shadow rendering framebuffer
		glGenFramebuffers(1, &shadowFB);
		glBindFramebuffer(GL_FRAMEBUFFER, shadowFB);
		glDrawBuffer(GL_NONE);
		glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, shadowArrayTex, 0);
		CHECK_FRAMEBUFFER_STATUS();
		glBindFramebuffer(GL_FRAMEBUFFER, 0);

		CHECK_GL_ERROR();

	}

	GLuint DragonDemo::loadShaderProgramFromFile(const char* filename, GLenum shaderType) {

		ifstream file(filename);
		if (!file) {
			cerr << "Unable to open file: " << filename << endl;
			return 0;
		}

		char line[256];
		string source;

		while (file) {
			file.getline(line, 256);
			source += line;
			source += '
';
		}

		if (!file.eof()) {
			cerr << "Error reading the file: " << filename << endl;
			return 0;
		}
		const GLchar *pText = static_cast<const GLchar *>(source.c_str());
		GLuint program = glCreateShaderProgramv(shaderType, 1, &pText);

		GLint status;
		glGetProgramiv(program, GL_LINK_STATUS, &status);
		if (status != GL_TRUE) {
			cerr << "Failed to compile/link shader program:" << endl;
			GLchar log[10000];
			glGetProgramInfoLog(program, 10000, NULL, log);
			cerr << log << endl;
			exit(1);
		}

		return program;

	}

	GLuint DragonDemo::createProgramPipeline(GLuint vertexShader, GLuint geometryShader, GLuint fragmentShader) {

		GLuint pipeline;
		glGenProgramPipelines(1, &pipeline);

		if (vertexShader != 0) glUseProgramStages(pipeline, GL_VERTEX_SHADER_BIT, vertexShader);
		if (geometryShader != 0) glUseProgramStages(pipeline, GL_GEOMETRY_SHADER_BIT, geometryShader);
		if (fragmentShader != 0) glUseProgramStages(pipeline, GL_FRAGMENT_SHADER_BIT, fragmentShader);

		glValidateProgramPipeline(pipeline);

		GLint status;
		glGetProgramPipelineiv(pipeline, GL_VALIDATE_STATUS, &status);
		if (status != GL_TRUE) {
			cerr << "Failed to validate program pipeline:" << endl;
			GLchar log[10000];
			glGetProgramPipelineInfoLog(pipeline, 10000, NULL, log);
			cerr << log << endl;
			exit(1);
		}

		return pipeline;

	}

	void DragonDemo::loadShaders() {

		cerr << "> Loading shaders..." << endl;

		// load G-buffer shaders
		GBufferVSP = loadShaderProgramFromFile("shaders/gbuffer.vs", GL_VERTEX_SHADER);
		GBufferFSP = loadShaderProgramFromFile("shaders/gbuffer.fs", GL_FRAGMENT_SHADER);
		GBufferPPL = createProgramPipeline(GBufferVSP, 0, GBufferFSP);

		// load light shaders
		lightVSP = loadShaderProgramFromFile("shaders/light.vs", GL_VERTEX_SHADER);
		lightGSP = loadShaderProgramFromFile("shaders/light.gs", GL_GEOMETRY_SHADER);
		lightFSP = loadShaderProgramFromFile("shaders/light.fs", GL_FRAGMENT_SHADER);
		lightPPL = createProgramPipeline(lightVSP, lightGSP, lightFSP);

		// load shadow shaders
		shadowMultiVSP = loadShaderProgramFromFile("shaders/shadow_multi.vs", GL_VERTEX_SHADER);
		shadowMultiGSP = loadShaderProgramFromFile("shaders/shadow_multi.gs", GL_GEOMETRY_SHADER);
		shadowMultiPPL = createProgramPipeline(shadowMultiVSP, shadowMultiGSP, 0);

		shadowSingleVSP = loadShaderProgramFromFile("shaders/shadow_single.vs", GL_VERTEX_SHADER);
		shadowSinglePPL = createProgramPipeline(shadowSingleVSP, 0, 0);
		lightIDUniformLoc = glGetUniformLocation(shadowSingleVSP, "lightID");
	}

	void DragonDemo::setupGBuffer() {

		cerr << "> Setting up G-buffer..." << endl;

		// create normal buffer
		glGenTextures(1, &positionGBT);
		glBindTexture(GL_TEXTURE_2D, positionGBT);
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, SCREEN_WIDTH, SCREEN_HEIGHT, 0, GL_RGBA, GL_FLOAT, NULL);
		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_MAG_FILTER, GL_NEAREST);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

		// create normal buffer
		glGenTextures(1, &normalGBT);
		glBindTexture(GL_TEXTURE_2D, normalGBT);
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, SCREEN_WIDTH, SCREEN_HEIGHT, 0, GL_RGB, GL_FLOAT, NULL);
		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_MAG_FILTER, GL_NEAREST);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

		// create depth buffer
		glGenTextures(1, &depthGBT);
		glBindTexture(GL_TEXTURE_2D, depthGBT);
		glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, SCREEN_WIDTH, SCREEN_HEIGHT, 0,
			GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
		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_MAG_FILTER, GL_NEAREST);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

		// create framebuffer and setup attachments
		glGenFramebuffers(1, &GBuffer);
		glBindFramebuffer(GL_FRAMEBUFFER, GBuffer);
		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, positionGBT, 0);
		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, normalGBT, 0);
		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthGBT, 0);

		const GLenum buffers[2] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 };
		glDrawBuffers(2, buffers);

		CHECK_FRAMEBUFFER_STATUS();
		glBindFramebuffer(GL_FRAMEBUFFER, 0);

		CHECK_GL_ERROR();

	}

	void DragonDemo::moveCamera(float dx, float dy, float dz, float dtime) {
		mat4 rotation = mat4(1.0f);
		rotation = rotate(rotation, camera.rotation.x, vec3(1.0f, 0.0f, 0.0f));
		rotation = rotate(rotation, camera.rotation.y, vec3(0.0f, 1.0f, 0.0f));
		rotation = rotate(rotation, camera.rotation.z, vec3(0.0f, 0.0f, 1.0f));
		camera.position += vec3(vec4(dtime*dx, dtime*dy, dtime*dz, 1.0f) * rotation);
		camera.position = clamp(camera.position, vec3(-7.5f, -5.5f, -7.5f), vec3(+7.5f, +5.5f, +7.5f));
	}

	void DragonDemo::rotateCamera(float dx, float dy, float dz, float dtime) {
		camera.rotation += vec3(dtime*dx, dtime*dy, dtime*dz);
		camera.rotation.x = clamp(camera.rotation.x, -90.0f, 90.0f);
	}

	void DragonDemo::renderScene(float dtime, bool useMultiShadow) {

		// update camera data to uniform buffer
		transform.ModelViewMatrix = mat4(1.0f);
		transform.ModelViewMatrix = rotate(transform.ModelViewMatrix, camera.rotation.x, vec3(1.0f, 0.0f, 0.0f));
		transform.ModelViewMatrix = rotate(transform.ModelViewMatrix, camera.rotation.y, vec3(0.0f, 1.0f, 0.0f));
		transform.ModelViewMatrix = rotate(transform.ModelViewMatrix, camera.rotation.z, vec3(0.0f, 0.0f, 1.0f));
		transform.ModelViewMatrix = translate(transform.ModelViewMatrix, -camera.position);
		transform.MVPMatrix = transform.ProjectionMatrix * transform.ModelViewMatrix;
		glBindBuffer(GL_UNIFORM_BUFFER, transformUB);
		glBufferData(GL_UNIFORM_BUFFER, sizeof(transform), &transform, GL_STATIC_DRAW);

		// update light information
		lightRotationFactor = fmodf(lightRotationFactor + dtime * 0.05, 1.f);
		updateLights();

		// render G-buffer
		glBindFramebuffer(GL_FRAMEBUFFER, GBuffer);
		glBindProgramPipeline(GBufferPPL);
		glBindVertexArray(vertexArray);

		glEnable(GL_DEPTH_TEST);
		glDisable(GL_BLEND);
		glClear(GL_DEPTH_BUFFER_BIT);

		glDrawElements(drawCommand.prim_type, drawCommand.indexCount, GL_UNSIGNED_INT, (GLvoid*)drawCommand.indexOffset);

		// render shadows
		if (useMultiShadow) {

			glBindFramebuffer(GL_FRAMEBUFFER, shadowFB);
			glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, shadowArrayTex, 0);
			glBindProgramPipeline(shadowMultiPPL);
			glViewport(0, 0, SHADOW_MAP_SIZE, SHADOW_MAP_SIZE);
			glClear(GL_DEPTH_BUFFER_BIT);
			glDrawElements(drawCommand.prim_type, drawCommand.indexCount, GL_UNSIGNED_INT, (GLvoid*)drawCommand.indexOffset);

		}
		else {

			glBindFramebuffer(GL_FRAMEBUFFER, shadowFB);
			glBindProgramPipeline(shadowSinglePPL);
			glViewport(0, 0, SHADOW_MAP_SIZE, SHADOW_MAP_SIZE);
			for (int i = 0; i < NUMBER_OF_LIGHTS; ++i) {
				glProgramUniform1i(shadowSingleVSP, lightIDUniformLoc, i);
				glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, shadowArrayTex, 0, i);
				glClear(GL_DEPTH_BUFFER_BIT);
				glDrawElementsInstanced(drawCommand.prim_type, drawCommand.indexCount, GL_UNSIGNED_INT, (GLvoid*)drawCommand.indexOffset, 4);
			}

		}

		// render lights
		glBindProgramPipeline(lightPPL);
		glBindFramebuffer(GL_FRAMEBUFFER, 0);
		glViewport(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);

		glDisable(GL_DEPTH_TEST);
		glBlendFunc(GL_ONE, GL_ONE);
		glEnable(GL_BLEND);
		glClear(GL_COLOR_BUFFER_BIT);

		glActiveTexture(GL_TEXTURE0);
		glBindTexture(GL_TEXTURE_2D, positionGBT);
		glActiveTexture(GL_TEXTURE1);
		glBindTexture(GL_TEXTURE_2D, normalGBT);
		glActiveTexture(GL_TEXTURE2);
		glBindTexture(GL_TEXTURE_2D, depthGBT);
		glActiveTexture(GL_TEXTURE3);
		glBindTexture(GL_TEXTURE_2D_ARRAY, shadowArrayTex);

		glDrawArraysInstanced(GL_POINTS, 0, 1, NUMBER_OF_LIGHTS);

		CHECK_GL_ERROR();

	}

} /* namespace dragon */

Things don’t maker sense in the light shaders:

Geometry shader:

#version 420 core

layout(std140, binding = 0) uniform transform {
	mat4 ModelViewMatrix;
	mat4 ProjectionMatrix;
	mat4 MVPMatrix;
	vec4 Viewport;
	float zNear;
	float zFar;
	float nearTop;
	float nearRight;
} Transform;

layout(std140, binding = 1) uniform lightPosArray {
	vec4 lightPos[100];
} LightPosArray;

layout(std140, binding = 1) uniform lightColorArray {
	vec4 lightColor[100];
} LightColorArray;


layout(points) in;
layout(triangle_strip, max_vertices = 4) out;

layout(location = 0) flat in int instanceID[];

layout(location = 0) out vec2 interpTexCoord;
layout(location = 1) out vec3 lightPosition;
layout(location = 2) out vec4 lightColor;
layout(location = 3) flat out int lightID;

out gl_PerVertex {
	vec4 gl_Position;
};

void main() {

	vec4 lightPos = LightPosArray.lightPos[instanceID[0]];
	lightColor = LightColorArray.lightColor[instanceID[0]];

	gl_Position = vec4( 1.0, 1.0, 0.5, 1.0 );
	interpTexCoord = vec2( 1.0, 1.0 );
	lightPosition = lightPos.xyz;
	lightID = instanceID[0];
	EmitVertex();

	gl_Position = vec4(-1.0, 1.0, 0.5, 1.0 );
	interpTexCoord = vec2( 0.0, 1.0 ); 
	lightPosition = lightPos.xyz;
	lightID = instanceID[0];
	EmitVertex();

	gl_Position = vec4( 1.0,-1.0, 0.5, 1.0 );
	interpTexCoord = vec2( 1.0, 0.0 ); 
	lightPosition = lightPos.xyz;
	lightID = instanceID[0];
	EmitVertex();

	gl_Position = vec4(-1.0,-1.0, 0.5, 1.0 );
	interpTexCoord = vec2( 0.0, 0.0 ); 
	lightPosition = lightPos.xyz;
	lightID = instanceID[0];
	EmitVertex();

	EndPrimitive();

}

Vertex shader:

#version 420 core

layout(location = 0) flat out int instanceID;

void main(void) {

	/* pass through instance ID */
	instanceID = gl_InstanceID;

}

Framgent shader:

#version 420 core

layout(std140, binding = 0) uniform transform {
	mat4 ModelViewMatrix;
	mat4 ProjectionMatrix;
	mat4 MVPMatrix;
	vec4 Viewport;
	float zNear;
	float zFar;
	float nearTop;
	float nearRight;
} Transform;

layout(std140, binding = 2) uniform lightTransform {
	mat4 VPMatrix[600];
} LightTransform;

layout(binding = 0) uniform sampler2D smpPositionBuffer;
layout(binding = 1) uniform sampler2D smpNormalBuffer;
layout(binding = 2) uniform sampler2D smpDepthBuffer;
layout(binding = 3) uniform sampler2DArrayShadow smpShadowMapArray;

layout(location = 0) in vec2 interpTexCoord;
layout(location = 1) in vec3 lightPosition;
layout(location = 2) in vec4 lightColor;
layout(location = 3) flat in int lightID;

layout(location = 0) out vec4 outFragmentColor;

void main(void) {

	/* reconstruct normal from X and Y component (not 100% accurate though
	   as Z can be sometimes negative due to perspective projection) */
	vec3 normal = texture(smpNormalBuffer, interpTexCoord).xyz;
	
	/* get position */
	vec4 position = texture(smpPositionBuffer, interpTexCoord);
	
	/* calculate attenuation */
	vec3 lightVec = lightPosition - position.xyz;
	float sqrDist = dot(lightVec, lightVec);
	float att = 1.f / (1.f + 0.01f * sqrDist);
	
	/* calculate diffuse */
	float diffuse = clamp(dot(normal, normalize(lightVec)), 0.f, 1.f);
	
	/* calculate projected shadow map coordinates */
	vec4 shadowCoordHom = LightTransform.VPMatrix[lightID] * position;
	
	/* we manually have to do the perspective divide as there is no
	   version of textureProj that can take a sampler2DArrayShadow */
	shadowCoordHom.xyz /= shadowCoordHom.w;
	shadowCoordHom.xyz = shadowCoordHom.xyz * 0.5 + 0.5;
	shadowCoordHom.z *= 0.9999;
	vec4 shadowCoord = vec4(shadowCoordHom.x, shadowCoordHom.y, lightID, shadowCoordHom.z);
	
	/* calculate shadow factor */
	float shadow = texture(smpShadowMapArray, shadowCoord);
	
	/* apply counter shadow eliminator factor */
	float counterShadow = min(floor(shadowCoord.w), 1.0f);
	shadow = mix(shadow, 1.f, counterShadow);

	outFragmentColor = lightColor * att * diffuse * shadow;
	
}

In the geometry shader lightID = instanceID[0] always.
interpTexCoord = vec2( 0.0, 1.0 ); I’ts a buffer the size of the screen so why is it something like 0.0, 1.0?

interpTexCoord is used for buffers in the fragment shader but as I said the buffers are the size of the screen.

And in the vertex shader check this out:

vec4 shadowCoord = vec4(shadowCoordHom.x, shadowCoordHom.y, lightID, shadowCoordHom.z);

Why would lightID be in a coord?

Is this unfinished code or something?
The code is given away for free, but what if I purchased the book :frowning:

All I’m looking for is multiple lighting and shadows, not head pain. :frowning:
Another day wasted…

Just sent them an email saying I’m not happy and have they working code? I doubt Ill get a reply.

Found an amasing demo: http://hd-prg.com/tileBasedShadows.html

Edit: It’s in ogl and well developed, have to keep looking elsewhere.

Gpu Pro 6 book has code, think the demo above is based on it.
https://www.amazon.co.uk/GPU-Pro-Advanced-Rendering-Techniques/dp/1482264617

Man is it getting complicated! Am used to GLFW and GLM.

Anyone got any advice?