Модель OpenGL (ES) в полупрозрачной модели - PullRequest
0 голосов
/ 15 марта 2012

Мне нужен эффект «Лицо в хрустальном шаре», когда у меня есть модель (лицо), которая делает вещи внутри полупрозрачной модели (хрустальный шар). Я чувствую, что принимаю сумасшедшие таблетки, потому что я просто не могу заставить это внутреннее лицо появиться частично покрытым шаром. Моя цель - изменить альфа шара (и / или лица), чтобы лицо появлялось и исчезало.

Ниже приведен соответствующий битовый код. Как вы увидите, я не использую шейдеры, просто старый добрый GL / GLES1. Если кто-нибудь скажет мне, что я делаю неправильно, я буду ОЧЕНЬ благодарен.

Код настройки ...

//-- CONFIGURATION ---------------
// Create The Depth Buffer Object
glGenRenderbuffersOES(1, &depth_renderbuffer);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, depth_renderbuffer);
glRenderbufferStorageOES(GL_RENDERBUFFER_OES, 
                         GL_DEPTH_COMPONENT16_OES, 
                         width, 
                         height);

// Create The FrameBuffer Object
glGenFramebuffersOES(1, &framebuffer);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, framebuffer);
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES,
                             GL_COLOR_ATTACHMENT0_OES,
                             GL_RENDERBUFFER_OES, 
                             color_renderbuffer);

glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, 
                             GL_DEPTH_ATTACHMENT_OES, 
                             GL_RENDERBUFFER_OES, 
                             depth_renderbuffer);

// Bind Color Buffer
glBindRenderbufferOES(GL_RENDERBUFFER_OES, color_renderbuffer);

glViewport(0, 0, width, height);

//-- LIGHTING ----------------------
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0); 

//-- PROJECTION ---------------------
glMatrixMode(GL_PROJECTION);
viewport_size = vec2((float) width,(float) height);

//Orthographic Projection
float max_x,max_y;
if(width>height){
    max_y = 1;
    max_x = (float)width/(float)height;
}
else{
    max_x = 1;
    max_y = (float)height/(float) width;
}
const float MAX_X = max_x;
const float MAX_Y = max_y;
const float Z_0 = 0;
const float MAX_Z = 1; 
glOrthof(-MAX_X, MAX_X, -MAX_Y, MAX_Y, Z_0-MAX_Z, Z_0+MAX_Z);

world_size = vec3(2*MAX_X,2*MAX_Y,2*MAX_Z);

//Color Depth
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE); //Dissapears if False
glDepthFunc(GL_LEQUAL);
glEnable(GL_BLEND);
//glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); //doesn't do it
glBlendFunc(GL_ONE, GL_ONE); //better

Вот вызов рендеринга

glClearColor(world->background_color.x,
             world->background_color.y,
             world->background_color.z,
             world->background_color.w);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

for(int s=0;s<surfaces.size();s++){
    Surface* surface = surface[s];

    glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, surface->getMatAmbient().Pointer());
    glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, surface->getMatDiffuse().Pointer());

    glMatrixMode(GL_MODELVIEW);

    //If I don't put this code in here (as opposed to above), the light gets all crazy! WHY!?
    glPushMatrix();
    glLoadIdentity();
    vec4 light_position = vec4(world->light->position,1);
    glLightfv(GL_LIGHT0,GL_POSITION,light_position.Pointer());

    glPopMatrix();


    glPushMatrix();
    glMultMatrixf(surface->transform.Pointer());

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, surface->index_buffer);
    glBindBuffer(GL_ARRAY_BUFFER, surface->vertex_buffer);

    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_NORMAL_ARRAY);

    glVertexPointer(3, GL_FLOAT, VERTEX_STRIDE, 0);
    glNormalPointer(GL_FLOAT, VERTEX_STRIDE, (GLvoid*) VERTEX_NORMAL_OFFSET);

    glDrawElements(GL_TRIANGLES, surface->indices.size(), GL_UNSIGNED_SHORT, 0);


    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_NORMAL_ARRAY);
    glPopMatrix();

}

Ответы [ 2 ]

3 голосов
/ 15 марта 2012

Звучит так, как будто вы страдаете от простого случая, когда концепция буфера глубины не применима к вашей сцене.Буфер глубины хранит одну глубину для каждого пикселя на экране, который в сцене с полностью непрозрачными объектами будет глубиной ближайшего объекта в этом пикселе.

Проблема заключается в том, что, когда вы хотите добавить частично прозрачные объектына сцене вы окажетесь в положении, когда несколько объектов вносят свой вклад в цвет отдельного пикселя.Но вы все равно можете хранить глубину только одного из них.

Итак, что, вероятно, происходит в вашем случае, так это то, что вы сначала рисуете хрустальный шар, и это помещает глубины различных пикселей хрустального шара вбуфер глубины.Затем вы пытаетесь нарисовать лицо, и OpenGL видит, что оно дальше, чем значения в буфере, поэтому пропускаете эти пиксели.

Таким образом, решение для быстрого исправления - просто изменить порядок вашей сцены.геометрия от руки так, что грань всегда рисуется перед хрустальным шаром, всегда находясь внутри.

В идеальном решении вы бы нарисовали всю непрозрачную геометрию за один шаг (традиционно в чем-то близком к переднейПоследовательный порядок, хотя это не так важно для PowerVR), чтобы установить непрозрачные значения глубины, затем всю прозрачную геометрию задом наперед, чтобы она была составлена ​​в правильном порядке.

В OpenGL вы действительно хотите порядокнекоторые вещи должны быть относительно фиксированными, чтобы вы могли передавать соответствующие значения в графический процессор и не понести расходы на связь.Люди по-прежнему имеют тенденцию делиться на непрозрачную и прозрачную геометрию и сначала рисуют непрозрачную, но часто они просто отключают запись в z-буфер, когда рисуют прозрачную геометрию, пытаясь сделать это что-то вроде порядка «назад-вперед», ноне тратя слишком много времени на решение этой проблемы.

Если вы готовы использовать чисто аддитивное смешивание, тогда ясно, что любой порядок ордеров для прозрачных пленок будет правильным, если в буфере глубины настроен непрозрачный материал.

2 голосов
/ 15 марта 2012

В каком порядке вы визуализируете объекты? Если вы рисуете мяч перед лицом, тогда все лицо будет отклонено, потому что оно находится позади шара в z-буфере. Если вы хотите сделать правильную прозрачность, вы должны визуализировать объекты сзади вперед.

А что касается вашего внутреннего вопроса: //If I don't put this code in here (as opposed to above), the light gets all crazy! WHY!?

Когда вы вызываете glLightfv с позицией, позиция преобразуется из того, что в данный момент находится в стеке матрицы вида модели. Вы должны поместить его в правильном месте относительно того, какую систему координат вы определяете координаты (это относительно координат вида, или мировых координат, или координат объекта?).

...