//creaza program shader din vertex shader si fragment shader
    //returneaza id-ul programului shader OpenGL
    unsigned int loadShader(const std::string &vertex_shader_file, const std::string &fragment_shader_file){
        //creaza o lista cu toate shaderele
        std::vector<unsigned int> shaders;
        shaders.push_back(_createShader(vertex_shader_file, GL_VERTEX_SHADER));
        shaders.push_back(_createShader(fragment_shader_file, GL_FRAGMENT_SHADER));

        std::cout << "Shader Loader : incarc shaderul compus din " << std::endl;
        std::cout << "\tvertex shader = " << vertex_shader_file << std::endl;
        std::cout << "\tframgnet shader = " << fragment_shader_file << std::endl;
        return _createProgram(shaders);
    }
Example #2
0
bool COpenGLGPUProgram::recreate(u32 uniforms, u32 attributes, u32 lights_count,
	E_VERTEX_SHADER_VERSION vertex_shader_ver, const c8 *vertex_shader,
	E_PIXEL_SHADER_VERSION pixel_shader_ver, const c8 *pixel_shader)
{
	u32 errors = 0;

	_destroyProgram();

	m_Program.u = glCreateProgram();

	// compiling shaders
	m_VertexShader.u = _createShader(
		GL_VERTEX_SHADER, vertex_shader, &errors);
	m_PixelShader.u = _createShader(
		GL_FRAGMENT_SHADER, pixel_shader, &errors);
	if (errors > 0)
	{
		_destroyProgram();
		return false;
	}

	// linking shaders into program
	glAttachShader(m_Program.u, m_VertexShader.u);
	glAttachShader(m_Program.u, m_PixelShader.u);

	for (u32 i = 0; i < E_ATTRIB_TYPE_COUNT; i++)
	{
		if (attributes & vid::AttribTypeBits[i])
			glBindAttribLocation(m_Program.u,
				getOGLAttribLocation((E_ATTRIB_TYPE)i),
				getAttribReadableName((E_ATTRIB_TYPE)i));
	}

	glLinkProgram(m_Program.u);

	GLint status = 0;
	glGetProgramiv(m_Program.u, GL_LINK_STATUS, &status);
	if (!status)
	{
		// check error message and log it
		GLint maxLength=0;
		GLsizei length;
		glGetProgramiv(m_Program.u, GL_INFO_LOG_LENGTH, &maxLength);
		GLchar *infoLog = new GLchar[maxLength];
		glGetProgramInfoLog(m_Program.u, maxLength, &length, infoLog);
		LOGGER.logErr("GLSL program linking errors:\n%s",
			(c8*)infoLog);
		delete [] infoLog;
		errors = errors + 1;
	}
	if (errors > 0)
	{
		_destroyProgram();
		return false;
	}

	// get uniforms information

	GLint num = 0, maxlen = 0;;
	glGetProgramiv(m_Program.u, GL_ACTIVE_UNIFORMS, &num);
	glGetProgramiv(m_Program.u, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxlen);

	// seems that some implementations use an extra null terminator
	++maxlen;
	core::array<c8> buf(maxlen);
	buf.set_used(maxlen);
	for (s32 i = 0; i < num && maxlen > 3; ++i)
	{
		GLint size;
		GLenum type;
		memset(buf.pointer(), 0, maxlen);
		glGetActiveUniform(
			m_Program.u, i, maxlen, 0, &size, &type, (GLchar*)buf.pointer());
		if (buf[0] == 'g' && buf[1] == 'l' && buf[2] == '_')
		{
			// skip OpenGL build-in uniforms
			continue;
		}
		GLint loc = glGetUniformLocation(m_Program.u, buf.pointer());
		if (size > 1)
		{
			s32 j = core::strlen(buf.pointer());
			while (j)
			{
				if (buf[j] == '[')
				{
					buf[j] = 0;
					break;
				}
				j--;
			}
		}
		E_UNIFORM_TYPE unitype = VIDEO_DRIVER.getUniformType(buf.pointer());
		if (unitype != EUT_NONE)
		{
			u32 size_bytes = 4;
			switch (type)
			{
			case GL_FLOAT:
				break;
			case GL_FLOAT_VEC2:
				size_bytes *= 2;
				break;
			case GL_FLOAT_VEC3:
				size_bytes *= 3;
				break;
			case GL_FLOAT_VEC4:
				size_bytes *= 4;
				break;
			case GL_FLOAT_MAT2:
				size_bytes *= 4;
				break;
			case GL_FLOAT_MAT3:
				size_bytes *= 9;
				break;
			case GL_FLOAT_MAT4:
				size_bytes *= 16;
				break;
			case GL_INT:
			case GL_SAMPLER_1D:
			case GL_SAMPLER_2D:
			case GL_SAMPLER_3D:
			case GL_SAMPLER_CUBE:
			case GL_SAMPLER_1D_SHADOW:
			case GL_SAMPLER_2D_SHADOW:
				break;
			case GL_INT_VEC2:
				size_bytes *= 2;
				break;
			case GL_INT_VEC3:
				size_bytes *= 3;
				break;
			case GL_INT_VEC4:
				size_bytes *= 4;
				break;
			default:
				LOGGER.logErr("Unknown OpenGL uniform type %X",
					type);
				errors++;
				break;
			}

			if (unitype == vid::EUT_LIGHTING)
			{
				if (size != lights_count)
				{
					LOGGER.logWarn("Incorrect lights count in GPU program (%d actual, %d expected)",
						size, lights_count);
					lights_count = size;
				}
			}
			m_Uniforms[unitype].Location = loc;
			m_Uniforms[unitype].Type = type;
			m_Uniforms[unitype].Size = size;
			m_Uniforms[unitype].Bytes = size * size_bytes;
		}
		else
		{
			LOGGER.logWarn("Unknown uniform '%s'", buf.pointer());
			errors++;
		}
	}

	// validating uniforms

	for (u32 i = 0; i < vid::E_UNIFORM_TYPE_COUNT; i++)
	{
		if (uniforms & vid::UniformTypeBits[i])
		{
			s32 location = m_Uniforms[i].Location;
			if (location == -1)
			{
				LOGGER.logErr("Can't validate uniform '%s'",
					getUniformName((E_UNIFORM_TYPE)i));
			}
		}
	}

	if (!errors)
		return CNullGPUProgram::recreate(uniforms, attributes, lights_count,
			vertex_shader_ver, vertex_shader,
			pixel_shader_ver, pixel_shader);
	return false;
}