C++ 使用phong照明的纹理贴图
我正在尝试将Phong照明添加到我的场景中,我在其中加载了带有纹理的网格。这是我的mesh loadin课程:C++ 使用phong照明的纹理贴图,c++,opengl,textures,phong,C++,Opengl,Textures,Phong,我正在尝试将Phong照明添加到我的场景中,我在其中加载了带有纹理的网格。这是我的mesh loadin课程: #define INVALID_OGL_VALUE 0xFFFFFFFF #define INVALID_MATERIAL 0xFFFFFFFF #define SAFE_DELETE(p) if (p) { delete p; p = NULL; } Mesh::MeshEntry::MeshEntry() { VB = INVALID_OGL_VALUE; IB
#define INVALID_OGL_VALUE 0xFFFFFFFF
#define INVALID_MATERIAL 0xFFFFFFFF
#define SAFE_DELETE(p) if (p) { delete p; p = NULL; }
Mesh::MeshEntry::MeshEntry()
{
VB = INVALID_OGL_VALUE;
IB = INVALID_OGL_VALUE;
NumIndices = 0;
MaterialIndex = INVALID_MATERIAL;
};
Mesh::MeshEntry::~MeshEntry()
{
if (VB != INVALID_OGL_VALUE)
{
glDeleteBuffers(1, &VB);
}
if (IB != INVALID_OGL_VALUE)
{
glDeleteBuffers(1, &IB);
}
}
void Mesh::MeshEntry::Init(const std::vector<Vertex>& Vertices,
const std::vector<unsigned int>& Indices)
{
NumIndices = Indices.size();
glGenBuffers(1, &VB);
glBindBuffer(GL_ARRAY_BUFFER, VB);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * Vertices.size(), &Vertices[0], GL_STATIC_DRAW);
glGenBuffers(1, &IB);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IB);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int) * NumIndices, &Indices[0], GL_STATIC_DRAW);
}
Mesh::Mesh()
{
}
Mesh::~Mesh()
{
Clear();
}
void Mesh::Clear()
{
for (unsigned int i = 0 ; i < textures_cnt.size() ; i++) {
SAFE_DELETE(textures_cnt[i]);
}
}
/*Loads mesh
*@Filename - name of the .obj file
**********************************************************/
bool Mesh::LoadMesh(const std::string& Filename){
Assimp::Importer Importer;
bool rc = false;
//clear previous loaded mesh
Clear();
//read file content
const aiScene* oScene = Importer.ReadFile(Filename.c_str(), aiProcess_Triangulate | aiProcess_GenSmoothNormals | aiProcess_FlipUVs );
if(oScene){
printf (" %i animations\n", oScene->mNumAnimations);
printf (" %i cameras\n", oScene->mNumCameras);
printf (" %i lights\n", oScene->mNumLights);
printf (" %i materials\n", oScene->mNumMaterials);
printf (" %i meshes\n", oScene->mNumMeshes);
printf (" %i textures\n", oScene->mNumTextures);
submeshes_cnt.resize(oScene->mNumMeshes);
textures_cnt.resize(oScene->mNumMaterials);
/*.........Initialize the meshes in the scene one by one...........*/
for (unsigned int i = 0 ; i < submeshes_cnt.size() ; i++) {
const aiMesh* paiMesh = oScene->mMeshes[i];
InitMesh(i, paiMesh);
}
// Extract the directory part from the file name
std::string::size_type SlashIndex = Filename.find_last_of("/");
std::string Dir;
if (SlashIndex == std::string::npos) {
Dir = ".";
}
else if (SlashIndex == 0) {
Dir = "/";
}
else {
Dir = Filename.substr(0, SlashIndex);
}
/*.................Initialization of meshes end....................*/
/*.............Initialize the materials.............................*/
for(unsigned int i = 0 ; i < oScene->mNumMaterials ; i++) {
const aiMaterial* pMaterial = oScene->mMaterials[i];
textures_cnt[i] = NULL;
if (pMaterial->GetTextureCount(aiTextureType_DIFFUSE) > 0) {
aiString Path;
if (pMaterial->GetTexture(aiTextureType_DIFFUSE, 0, &Path, NULL, NULL, NULL, NULL, NULL) == AI_SUCCESS) {
std::string FullPath = Dir + "/" + Path.data;
textures_cnt[i] = new Texture(GL_TEXTURE_2D, FullPath.c_str());
if (!textures_cnt[i]->Load()) {
printf("Error loading texture '%s'\n", FullPath.c_str());
delete textures_cnt[i];
textures_cnt[i] = NULL;
rc = false;
}
else {
printf("Loaded texture '%s'\n", FullPath.c_str());
}
}
}
}
/*.................Initialization of materials end....................*/
}
else {
printf("Error parsing '%s': '%s'\n", Filename.c_str(), Importer.GetErrorString());
}
return rc;
}
void Mesh::InitMesh(unsigned int Index, const aiMesh* paiMesh)
{
submeshes_cnt[Index].MaterialIndex = paiMesh->mMaterialIndex;
std::vector<Vertex> Vertices;
std::vector<unsigned int> Indices;
const aiVector3D Zero3D(0.0f, 0.0f, 0.0f);
for (unsigned int i = 0 ; i < paiMesh->mNumVertices ; i++) {
const aiVector3D* pPos = &(paiMesh->mVertices[i]);
const aiVector3D* pNormal = &(paiMesh->mNormals[i]);
const aiVector3D* pTexCoord = paiMesh->HasTextureCoords(0) ? &(paiMesh->mTextureCoords[0][i]) : &Zero3D;
Vertex v(Vector3f(pPos->x, pPos->y, pPos->z),
Vector2f(pTexCoord->x, pTexCoord->y),
Vector3f(pNormal->x, pNormal->y, pNormal->z));
Vertices.push_back(v);
}
for (unsigned int i = 0 ; i < paiMesh->mNumFaces ; i++) {
const aiFace& Face = paiMesh->mFaces[i];
assert(Face.mNumIndices == 3);
Indices.push_back(Face.mIndices[0]);
Indices.push_back(Face.mIndices[1]);
Indices.push_back(Face.mIndices[2]);
}
submeshes_cnt[Index].Init(Vertices, Indices);
}
void Mesh::Render(){
//enable VAOs for vertices, normals, textures
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
for(unsigned int i = 0 ; i < submeshes_cnt.size() ; i++){
glBindBuffer(GL_ARRAY_BUFFER, submeshes_cnt[i].VB);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*)12);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*)20);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, submeshes_cnt[i].IB);
const unsigned int MaterialIndex = submeshes_cnt[i].MaterialIndex;
if (MaterialIndex < textures_cnt.size() && textures_cnt[MaterialIndex]) {
textures_cnt[MaterialIndex]->Bind(GL_TEXTURE0);
}
glDrawElements(GL_TRIANGLES, submeshes_cnt[i].NumIndices, GL_UNSIGNED_INT, 0);
}
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
}
片段着色器:
#version 420
uniform sampler2D tex;
in vec2 fragTexCoord;
out vec4 finalColor;
void main() {
//note: the texture function was called texture2D in older versions of GLSL
finalColor = texture(tex, fragTexCoord);
}
这就是我得到的:
但当我尝试添加phong照明时,当我将法线属性添加到顶点着色器时,我得到的是:
问题在哪里?
谢谢你的帮助
//编辑
着色器加载和链接
shprogram::shprogram(const std::vector<shader>& shaders) :
_object(0)
{
if(shaders.size() <= 0)
throw std::runtime_error("No shaders were provided to create the program");
//create the program object
_object = glCreateProgram();
if(_object == 0)
throw std::runtime_error("glCreateProgram failed");
//attach all the shaders
for(unsigned i = 0; i < shaders.size(); ++i)
glAttachShader(_object, shaders[i].getObject());
//link the shaders together
glLinkProgram(_object);
//detach all the shaders
for(unsigned i = 0; i < shaders.size(); ++i)
glDetachShader(_object, shaders[i].getObject());
//throw exception if linking failed
GLint status;
glGetProgramiv(_object, GL_LINK_STATUS, &status);
if (status == GL_FALSE) {
std::string msg("Program linking failure: ");
GLint infoLogLength;
glGetProgramiv(_object, GL_INFO_LOG_LENGTH, &infoLogLength);
char* strInfoLog = new char[infoLogLength + 1];
glGetProgramInfoLog(_object, infoLogLength, NULL, strInfoLog);
msg += strInfoLog;
delete[] strInfoLog;
glDeleteProgram(_object); _object = 0;
throw std::runtime_error(msg);
}
}
shprogram::~shprogram() {
//might be 0 if ctor fails by throwing exception
if(_object != 0) glDeleteProgram(_object);
}
GLuint shprogram::object() const {
return _object;
}
void shprogram::use() const {
glUseProgram(_object);
}
bool shprogram::isInUse() const {
GLint currentProgram = 0;
glGetIntegerv(GL_CURRENT_PROGRAM, ¤tProgram);
return (currentProgram == (GLint)_object);
}
void shprogram::stopUsing() const {
assert(isInUse());
glUseProgram(0);
}
GLint shprogram::attrib(const GLchar* attribName) const {
if(!attribName)
throw std::runtime_error("attribName was NULL");
GLint attrib = glGetAttribLocation(_object, attribName);
if(attrib == -1)
throw std::runtime_error(std::string("Program attribute not found: ") + attribName);
return attrib;
}
GLint shprogram::uniform(const GLchar* uniformName) const {
if(!uniformName)
throw std::runtime_error("uniformName was NULL");
GLint uniform = glGetUniformLocation(_object, uniformName);
if(uniform == -1)
throw std::runtime_error(std::string("Program uniform not found: ") + uniformName);
return uniform;
}
void shprogram::setUniformMatrix2(const GLchar* name, const GLfloat* v, GLsizei count, GLboolean transpose) {
assert(isInUse());
glUniformMatrix2fv(uniform(name), count, transpose, v);
}
void shprogram::setUniformMatrix3(const GLchar* name, const GLfloat* v, GLsizei count, GLboolean transpose) {
assert(isInUse());
glUniformMatrix3fv(uniform(name), count, transpose, v);
}
void shprogram::setUniformMatrix4(const GLchar* name, const GLfloat* v, GLsizei count, GLboolean transpose) {
assert(isInUse());
glUniformMatrix4fv(uniform(name), count, transpose, v);
}
void shprogram::setUniform(const GLchar* name, const glm::mat2& m, GLboolean transpose) {
assert(isInUse());
glUniformMatrix2fv(uniform(name), 1, transpose, glm::value_ptr(m));
}
void shprogram::setUniform(const GLchar* name, const glm::mat3& m, GLboolean transpose) {
assert(isInUse());
glUniformMatrix3fv(uniform(name), 1, transpose, glm::value_ptr(m));
}
void shprogram::setUniform(const GLchar* name, const glm::mat4& m, GLboolean transpose) {
assert(isInUse());
glUniformMatrix4fv(uniform(name), 1, transpose, glm::value_ptr(m));
}
void shprogram::setUniform(const GLchar* uniformName, const glm::vec3& v) {
setUniform3v(uniformName, glm::value_ptr(v));
}
void shprogram::setUniform(const GLchar* uniformName, const glm::vec4& v) {
setUniform4v(uniformName, glm::value_ptr(v));
}
既不能在着色器源中明确设置属性位置,也不能在链接着色器之前绑定属性位置,也不能查询属性位置。总账可以自由地对任何活动输入属性使用任何有效的属性索引
假设0是位置,1是texcoord,2是法线。对于position+texcoord的情况,这可能是偶然的,但是当您添加法线时,索引可能会混淆。在GLSL代码中使用
布局(位置=…)
(有关详细信息,请参见),或者使用指定所需的映射。请提供着色器编译和链接代码。到目前为止,我的猜测是您没有指定属性位置。您的问题中有可用于查询顶点属性位置的代码(GLint shprogram::attrib(const GLchar*attribName)const
),但您没有使用它!茨克茨克。另外,考虑重新命名这个函数,因为可以在顶点属性位置上执行多个操作-您可以在链接之后查询它们,可以在链接之前绑定它们,等等。这条规则有一个例外,尽管它不适用于这里glVertexPointer(…)
(用于在固定函数OpenGL中设置顶点位置指针的函数)是唯一将别名(或至少在兼容实现中允许)添加到GLSL中属性槽的指针函数——它将别名添加到0
。我认为这种行为导致了很多假设,即属性槽总是以顺序方式工作,或者绑定属性位置是不必要的;可悲的是,我认为定义这种行为弊大于利:-\@AndonM.Coleman:呵呵,比这更糟。在兼容模式下,属性0有点特殊,因为它完全兼容所有旧的顶点规范功能-调用glVertexAttrib(0,…)
内部glBegin()/End()
实际上会发出顶点。。。奇怪的东西。
shprogram::shprogram(const std::vector<shader>& shaders) :
_object(0)
{
if(shaders.size() <= 0)
throw std::runtime_error("No shaders were provided to create the program");
//create the program object
_object = glCreateProgram();
if(_object == 0)
throw std::runtime_error("glCreateProgram failed");
//attach all the shaders
for(unsigned i = 0; i < shaders.size(); ++i)
glAttachShader(_object, shaders[i].getObject());
//link the shaders together
glLinkProgram(_object);
//detach all the shaders
for(unsigned i = 0; i < shaders.size(); ++i)
glDetachShader(_object, shaders[i].getObject());
//throw exception if linking failed
GLint status;
glGetProgramiv(_object, GL_LINK_STATUS, &status);
if (status == GL_FALSE) {
std::string msg("Program linking failure: ");
GLint infoLogLength;
glGetProgramiv(_object, GL_INFO_LOG_LENGTH, &infoLogLength);
char* strInfoLog = new char[infoLogLength + 1];
glGetProgramInfoLog(_object, infoLogLength, NULL, strInfoLog);
msg += strInfoLog;
delete[] strInfoLog;
glDeleteProgram(_object); _object = 0;
throw std::runtime_error(msg);
}
}
shprogram::~shprogram() {
//might be 0 if ctor fails by throwing exception
if(_object != 0) glDeleteProgram(_object);
}
GLuint shprogram::object() const {
return _object;
}
void shprogram::use() const {
glUseProgram(_object);
}
bool shprogram::isInUse() const {
GLint currentProgram = 0;
glGetIntegerv(GL_CURRENT_PROGRAM, ¤tProgram);
return (currentProgram == (GLint)_object);
}
void shprogram::stopUsing() const {
assert(isInUse());
glUseProgram(0);
}
GLint shprogram::attrib(const GLchar* attribName) const {
if(!attribName)
throw std::runtime_error("attribName was NULL");
GLint attrib = glGetAttribLocation(_object, attribName);
if(attrib == -1)
throw std::runtime_error(std::string("Program attribute not found: ") + attribName);
return attrib;
}
GLint shprogram::uniform(const GLchar* uniformName) const {
if(!uniformName)
throw std::runtime_error("uniformName was NULL");
GLint uniform = glGetUniformLocation(_object, uniformName);
if(uniform == -1)
throw std::runtime_error(std::string("Program uniform not found: ") + uniformName);
return uniform;
}
void shprogram::setUniformMatrix2(const GLchar* name, const GLfloat* v, GLsizei count, GLboolean transpose) {
assert(isInUse());
glUniformMatrix2fv(uniform(name), count, transpose, v);
}
void shprogram::setUniformMatrix3(const GLchar* name, const GLfloat* v, GLsizei count, GLboolean transpose) {
assert(isInUse());
glUniformMatrix3fv(uniform(name), count, transpose, v);
}
void shprogram::setUniformMatrix4(const GLchar* name, const GLfloat* v, GLsizei count, GLboolean transpose) {
assert(isInUse());
glUniformMatrix4fv(uniform(name), count, transpose, v);
}
void shprogram::setUniform(const GLchar* name, const glm::mat2& m, GLboolean transpose) {
assert(isInUse());
glUniformMatrix2fv(uniform(name), 1, transpose, glm::value_ptr(m));
}
void shprogram::setUniform(const GLchar* name, const glm::mat3& m, GLboolean transpose) {
assert(isInUse());
glUniformMatrix3fv(uniform(name), 1, transpose, glm::value_ptr(m));
}
void shprogram::setUniform(const GLchar* name, const glm::mat4& m, GLboolean transpose) {
assert(isInUse());
glUniformMatrix4fv(uniform(name), 1, transpose, glm::value_ptr(m));
}
void shprogram::setUniform(const GLchar* uniformName, const glm::vec3& v) {
setUniform3v(uniformName, glm::value_ptr(v));
}
void shprogram::setUniform(const GLchar* uniformName, const glm::vec4& v) {
setUniform4v(uniformName, glm::value_ptr(v));
}
//bind shader program
gProgram->use();
//set the "camera" uniform
gProgram->setUniform("camera", gCamera.matrix());
//set the "model" uniform in the vertex shader, based on the gDegreesRotated global
gProgram->setUniform("model", glm::rotate(glm::mat4(), 150.0f ,glm::vec3(0,1,0)));
gProgram->setUniform("light.position", gLight.position);
gProgram->setUniform("light.intensities", gLight.intensities);