左边就是缺失的情况,右边是修复后的。
模型:
https://mega.co.nz/#!nAUARKAI!fM4iJWbl01UYGDbP8bEKQz7GyMklF_TWZsHCEvRUELg
--文章很长,描述了解决问题的过程,如果只需要解决方案的话,请自行翻页到最后。--
模型:
https://mega.co.nz/#!nAUARKAI!fM4iJWbl01UYGDbP8bEKQz7GyMklF_TWZsHCEvRUELg
--文章很长,描述了解决问题的过程,如果只需要解决方案的话,请自行翻页到最后。--
非常折腾的一个问题,模型在assimp viewer里面看是正常的,并且调试以后材质数据都是正确加载进来的。
一开始以为是0.8.0之后使用 OpenGL 3.x/4.x 的关系,光照什么在3.0之后的版本都被弃用的关系。写了如下的代码测试:
#include "ofApp.h"
float no_mat[] = {0.0f, 0.0f, 0.0f, 1.0f};
float mat_ambient[] = {0.0215, 0.1745, 0.0215, 1.0};
float mat_diffuse[] = {0.07568, 0.61424, 0.07568, 1.0};
float mat_specular[] = {0.633, 0.727811, 0.633, 1.0};
float low_shininess = 15.0f;
//light properties
float ambient[] = {0.5f, 0.5f, 0.5f, 1.0f};
float diffuse[] = {1.0f, 1.0f, 1.0f, 1.0f};
float specular[] = {1.0f, 1.0f, 1.0f, 1.0f};
float position[] = {100.0f, 100.0f, 100.0f, 0.0f};
void ofApp::setup(){
glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
glLightfv(GL_LIGHT0, GL_POSITION, position);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH);
}
void ofApp::draw(){
cam.begin();
ofPushMatrix();
ofTranslate(0, 0);
glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialf(GL_FRONT, GL_SHININESS, low_shininess);
glMaterialfv(GL_FRONT, GL_EMISSION, no_mat);
ofSphere(0, 0, 50);
ofPopMatrix();
cam.end();
}
结果“果然”不通过,提交了issue上去以后,就一口气钻进到glfw的OpenGL版本问题里面去了。然后又做了一些测试:
int main( ){
ofAppGLFWWindow* window = new ofAppGLFWWindow();
window->setOpenGLVersion(4, 3); // should be default value, but if i use this, ofSphere() gone
// window->setOpenGLVersion(3, 2); // same with (4, 3)
// window->setOpenGLVersion(2, 1); // glfwCreateWindow failed
ofSetupOpenGL(window, 512,512,OF_WINDOW); // <-------- setup the GL context ofRunApp(new ofApp());
}
版本这条路似乎很不平坦。
虽然 setOpenGLVersion() 是不允许外部调用的(口头上的限制 :) ) 实际上是有效的,但是明显是有一些bug在里面的。
修改了version以后会对调用一些glfw的Hint。
虽然 setOpenGLVersion() 是不允许外部调用的(口头上的限制 :) ) 实际上是有效的,但是明显是有一些bug在里面的。
修改了version以后会对调用一些glfw的Hint。
void ofAppGLFWWindow::setupOpenGL(int w, int h, int screenMode){
...
if(glVersionMinor!=-1 && glVersionMajor!=-1){
glfwWindowHint(GLFW_RESIZABLE, GL_TRUE);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, glVersionMajor);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, glVersionMinor);
if(glVersionMajor>=3){
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
}
#ifdef TARGET_OPENGLES
glfwWindowHint(GLFW_CLIENT_API,GLFW_OPENGL_ES_API);
#endif
}
...
}
在谷歌上查看了一些OpenGL版本变动的东西:
Here are some commonly used but deprecated functions:Also anything that goes between glBegin and glEnd:
- glBegin(...)
- glEnd()
- glCallList(...)
- glColor*
- glMaterial*
- glVertexPointer
All the matrix operations:
- glVertex*
- glNormal*
- glTexCoord*
- glMultiTexCoord*
The 'old' method refers to what is known as the fixed function pipeline.
- glRotate*
- glTranslate*
- glScale*
- glMatrixMode()
- glLoadIdentity()
- glPushMatrix()
- glPopMatrix()
- glFrustum()
- gluPerspective(...)
- gluLookAt(..)
如此之多的东西都被弃用了...好多很常用像Matrix类的。
总觉得很奇怪,又做了一些测试:
总觉得很奇怪,又做了一些测试:
int main( ){
ofSetCurrentRenderer(ofGLRenderer::TYPE); // 默认是 ofGLProgrammableRenderer,里面满是shader
ofSetLogLevel(OF_LOG_VERBOSE); // 在0.8.0里面可以显示版本信息
ofAppGlutWindow* window = new ofAppGlutWindow();
ofSetupOpenGL(window, 512,512,OF_WINDOW); // <-------- setup the GL context
ofRunApp(new ofApp());
}
改用旧的 ofAppGlutWindow 和 ofGLRender,发现好多例子都是正常的。比如好多例子里面用了 ofPushMatrix() 里面用的就是 glPushMatrix(),按理说是被弃用的。也就是说目前的oF的OpenGL API是向下兼容的,那光照理应正常工作?
glBegin(GL_TRIANGLES);
glVertex2f(10, 10);
glVertex2f(50, 10);
glVertex2f(50, 50);
glEnd();
尝试了一下用OpenGL API绘制一个三角形,这下光照有效了。看来问题在 ofSphere()里面,用差异工具对比了一下0.8.0和0.7.4的ofSphere()。虽然mesh这块变化很大(0.8.0里面有专门的3D primitive类),但最后的数据应该是相同的。终于:
void ofGLRenderer::drawSphere(float x, float y, float z, float radius) {
glEnable(GL_NORMALIZE);
glPushMatrix();
glScalef(radius, radius, radius);
if(bFilled) {
sphereMesh.draw();
} else {
sphereMesh.drawWireframe();
}
glPopMatrix();
glDisable(GL_NORMALIZE);
}
单击此处进行编辑.
法线啊~~oF 在绘制3D图元都是通过单位图元放大缩小来做的 ( scale matrix ),应该是影响到了 T T。0.8.0 里面ofDrawSphere/Box 之类里面就没有调用glEnable(GL_NORMALIZE) 了。
一个阶段的问题解决了:
(PS. 0.8.0 这个是在 ofEnableLighting()里面调用,glfw及ProgrammableRender带来的变化是深远的 T T )
一个阶段的问题解决了:
(PS. 0.8.0 这个是在 ofEnableLighting()里面调用,glfw及ProgrammableRender带来的变化是深远的 T T )
glEnable(GL_NORMALIZE);
ofSphere(0, 0, 50);
glDisable(GL_NORMALIZE);
接下来回到最初的问题,既然材质在0.8.0里面也是有效的,为什么assimp会显示不了材质呢?
偶然发现在example->3d里面有一个3DPrimitiveExample,之前在对比的时候看到0.8.0是有自己的3D图元类的,有点兴趣就编译了一下。
偶然发现在example->3d里面有一个3DPrimitiveExample,之前在对比的时候看到0.8.0是有自己的3D图元类的,有点兴趣就编译了一下。
这边材质正常??里面确实用到了 ofMaterial ,不过马上就失望了。
// shininess is a value between 0 - 128, 128 being the most shiny //
material.setShininess( 15 );
// the light highlight of the material //
material.setSpecularColor(ofColor(255, 255, 255, 255));
// 这是我加的
material.setAmbientColor(ofColor(100, 255, 100, 255));
material.setDiffuseColor(ofColor(50, 200, 50, 255));
材质还是无效,结果还是如上图,Ambient和diffuse的颜色明显不对。试着把之前光照的代码帮过来,去掉ofLight,ofMaterial没动,没太多奇怪的地方:
glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
glLightfv(GL_LIGHT0, GL_POSITION, position);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
OK,终于正确显示材质了。
这下就知道问题出在 ofLight 里面了。
//----------------------------------------
void ofEnableLighting() {
glEnable(GL_LIGHTING);
#ifndef TARGET_OPENGLES //TODO: fix this - 修复什么?
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
#endif
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_NORMALIZE);
}
//----------------------------------------
void ofDisableLighting() {
glDisable(GL_LIGHTING);
if(!normalsEnabled){
glDisable(GL_NORMALIZE);
}
}
居然在 ofEnableLighting 里面启用了 GL_COLOR_MATERIAL ,T T 怪不得材质失效了。0.7.4 里面也是这样的,当初是出于什么原因加了这?
既然知道问题在这了,那就好办了。简单修复可以这样子做:(问题已提交,可以等官方修复)
既然知道问题在这了,那就好办了。简单修复可以这样子做:(问题已提交,可以等官方修复)
void ofApp::setup(){
...
ofEnableDepthTest();
glShadeModel(GL_SMOOTH); //some model / light stuff
// light.enable();
ofEnableSeparateSpecularLight();
}
void ofApp::draw(){
ofSetColor(255);
glEnable(GL_LIGHTING);
glEnable(GL_NORMALIZE);
glEnable(GL_LIGHT0);
ofPushMatrix();
ofTranslate(model.getPosition().x+100, model.getPosition().y, 0);
ofRotate(-mouseX, 0, 1, 0);
ofTranslate(-model.getPosition().x, -model.getPosition().y, 0);
model.drawFaces();
ofPopMatrix();
glDisable(GL_LIGHT0);
glDisable(GL_NORMALIZE);
glDisable(GL_LIGHTING);