Я пишу glsl-шейдер для манипулятора вращения. Я нацелен на стиль Autodesk Maya, 3 оси для каждого из поворотов x y и z и одну ось над ними для вращения по прямой вперед камеры равна 4;OpenGL выборочный вывод в один из двух текстур в одном фрагменте шейдера
Пользователь может ограничить результат своих манипуляций определенной осью, выбрав его непосредственно в окне просмотра.
Чтобы включить выбор объекта, я использую custrom framebuffer с 2 прикрепленными текстурами в качестве целей рендеринга - один для цвета, один для идентификаторов выбора.
Проблема в том, что наличие 4 осей, нарисованных режимом GL_LINES, создает проблему для пользователя. Если линии нарисованы тонким и приятным, пользователь должен щелкнуть по ним очень точно, чтобы активировать определенную ось, потому что он должен выбрать более резкий пиксель с соответствующим object_id оси. Я хочу облегчить его жизнь, сделав 2 отдельных рисунка. Тонкие линии для вывода цвета и в 3 раза более широкие линии для текстуры вывода объекта.
Я новичок в openGL. Теперь моя наивная логика передает булевскую форму, которая сообщает шейдеру фрагмента фрагмента рисовать в цвет или в буфер объектива.
Вот команды рисования с селектором прошли render_target
GLfloat lw;
glGetFloatv(GL_LINE_WIDTH,&lw);
glUniform1ui(7,0);//render to RGB
glDrawArrays(GL_POINTS,0,1);
glUniform1ui(7,1);//render to OBJECTID
glLineWidth(10);
glDrawArrays(GL_POINTS,0,1);
glLineWidth(lw);
А вот фрагмент шейдера:
#version 450
//inputs
layout(location=6) uniform uint manipulator_selected_axis;
layout(location=7) uniform uint render_to_selection_buffer;
//outputs
layout(location=0) out vec4 out_color;
layout(location=1) out float out_objectid;
void main(void)
{
if (render_to_selection_buffer==1)
{
switch (gl_PrimitiveID)
{
case 0: //CAMERA FORWARD
out_objectid=float(253)/256;
break;
case 1: //X
out_objectid=float(250)/256;
break;
case 2: //Y
out_objectid=float(251)/256;
break;
case 3: //Z
out_objectid=float(252)/256;
break;
}
out_color=vec4(0,0,0,0);
}
else
{
vec4 active_axis_color=vec4(1.0,1.0,0.0,1.0);
switch(gl_PrimitiveID)
{
case 0: //CAMERA FORWARD
if(manipulator_selected_axis==0)
out_color=active_axis_color;
else
out_color =vec4(1.0,0.5,1.0,1.0);
break;
case 1: //X
if(manipulator_selected_axis==1)
out_color=active_axis_color;
else
out_color =vec4(1.0,0.0,0.0,1.0);
break;
case 2: //Y
if(manipulator_selected_axis==2)
out_color=active_axis_color;
else
out_color =vec4(0.0,1.0,0.0,1.0);
break;
case 3: //Z
if(manipulator_selected_axis==3)
out_color=active_axis_color;
else
out_color =vec4(0.0,0.0,1.0,1.0);
break;
case 4:
out_color =vec4(0.6,0.6,0.6,1.0);
break;
}
out_objectid=0;
}
}
Я действительно не»как логики, я использую для этого, потому что он выглядит уродливым и неоптимизированным. Во-первых, поскольку шейдер должен запускаться дважды, и у него есть довольно сложный шейдер геометрии, где я создаю круги. Во-вторых, потому что у моего фрагментарного шейдера есть много, если еще что-то там, и мне сказали, что gpu не любит разветвления.
Так ВОПРОС 1 Каков альтернативный способ записи такого шейдера, который делает то же самое? ВОПРОС 2 более технический.
Здесь я предоставить скриншот того, что я получаю от theese 2 glDrawArrays позвонить. Как вы можете видеть, у меня есть черные контуры в моем colorbuffer. Проблема заключается в том, что когда шейдер framgent выполняет код визуализации для цели out_objectid, он все еще записывает какую-то грязную случайную информацию в out_color, как на рисунке ниже, поэтому мне пришлось переопределить ее с помощью out_color = vec4 (0,0,0, 0). По крайней мере, он дает чистый черный цвет.
ВОПРОС 2. Где моя ошибка? Как заблокировать блок objectid для записи в out_color? Спасибо UPDATE: После того, что я предложил, я пришел к такому эффекту. Я не могу описать, что происходит во внутренности openGL. Похоже, он все еще пишет GL_DEPTH_COMPONENT и делает некоторые неопределенные глубинные тесты, которые приводят к такому результату. Я не хочу, чтобы во время этого вызова рисования была записана глубина, потому что манипулятор всегда на вершине. Возможно, вы могли бы дать мне дополнительные советы.
рисования Код
glBindBuffer(GL_ARRAY_BUFFER,0);
glUseProgram(program_id_ctl_manip_color);
glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
glUniform4f(0,0,0,0,1);
glUniform1f(5,0.67);
glUniform1ui(6,manipulator_axis_highlight);
glUniformMatrix4fv(10,1,GL_TRUE,cam.matrix_view.m);
glUniformMatrix4fv(14,1,GL_TRUE,cam.matrix_projection_ortho.m);
glUniformMatrix4fv(18,1,GL_TRUE,cam.matrix_camera.m);
glDrawBuffer(GL_COLOR_ATTACHMENT0);
glDrawArrays(GL_POINTS,0,1);
GLfloat lw;
glGetFloatv(GL_LINE_WIDTH,&lw);
glLineWidth(6);
glUseProgram(program_id_ctl_manip_objectid);
glUniform4f(0,0,0,0,1);
glUniform1f(5,0.67);
glUniform1ui(6,manipulator_axis_highlight);
glUniformMatrix4fv(10,1,GL_TRUE,cam.matrix_view.m);
glUniformMatrix4fv(14,1,GL_TRUE,cam.matrix_projection_ortho.m);
glUniformMatrix4fv(18,1,GL_TRUE,cam.matrix_camera.m);
glDrawBuffer(GL_COLOR_ATTACHMENT1);
glDrawArrays(GL_POINTS,0,1);
GLenum buffers[2]={GL_COLOR_ATTACHMENT0,GL_COLOR_ATTACHMENT1};
glDrawBuffers(2,buffers);
glLineWidth(lw);
Большое спасибо. Это было полезно. Я также думал, что glLineWidth может быть устаревшим, но не успел это проверить. Пока я буду использовать его, но скоро перейду к современному. Так как я понял, что минимальный способ изменения вещей в моей ситуации - это отпирать привязанность к out_color и максимальному созданию 2 шейдеров. Я тоже рассматривал это, и у меня возник вопрос в том, что у меня есть 2 флеш-шейдера в одной программе. Возможно ли это, или я должен скомпилировать и связать две отдельные программы? Я не хочу излишней компиляции моей программы компиляции. Хотите, чтобы это было как можно проще. – Antiusninja
Просто создание 2 отдельных шейдеров фрагментов не выполняет эту работу. Как именно я должен отключить свой цветовой буфер? Прямо сейчас у меня есть только один буфер с двумя цветными вложениями? Как правильно отвязать одну из текстур? – Antiusninja
Как я уже сказал, измените буфер рисования. – derhass