2013-06-09 2 views
6

Я хочу перенести инициализацию моей 3D-текстуры с центрального процессора на GPU. В качестве теста я написал шейдер, чтобы установить все вокселы в постоянное значение, но текстура вообще не изменяется. Как мне заставить работать?Вычислить шейдер, не изменяя 3d-текстуру

Вычислительный шейдер:

#version 430 

layout(local_size_x=1, local_size_y=1, local_size_z=1) in; 
layout(r8, location = 0) uniform image3D volume; 

void main() 
{ 
    imageStore(volume, ivec3(gl_WorkGroupID), vec4(0)); 
} 

Призывание:

glEnable(GL_TEXTURE_3D); 
glActiveTexture(GL_TEXTURE0); 
glGenTextures(1, &volume_tid); 
glBindTexture(GL_TEXTURE_3D, volume_tid); 
glTexImage3D(GL_TEXTURE_3D, 0, GL_R8, volume_dims[0], volume_dims[1], volume_dims[2], 0, GL_RED, GL_UNSIGNED_BYTE, voxels); 

ShaderProgram computeVolumeShader; 
computeVolumeShader.loadShader(GL_COMPUTE_SHADER, "compute_volume.glsl"); 
computeVolumeShader.link(); 
computeVolumeShader.use(); 
computeVolumeShader.uniform("volume", 0); 
glBindImageTexture(0, volume_tid, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R8); 
glDispatchCompute(volume_dims[0], volume_dims[1], volume_dims[2]); 
glBindImageTexture(0, 0, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R8); 
computeVolumeShader.unUse(); 
glMemoryBarrier(GL_ALL_BARRIER_BITS); 

Примечание: voxels подается в glTexImage3D содержит данные CPU инициализирован.

+0

Вы пробовали использовать реальный формат изображения вместо 'GL_RED'? –

+0

@Nicol Когда я использую 'GL_R8UI', я больше ничего не вижу, даже без вычислительного шейдера. Я использую 'sampler3D' для рендеринга, разве это имеет значение? Поскольку 'GL_RED' указан [здесь] (http://www.opengl.org/sdk/docs/man/xhtml/glTexImage3D.xml) в таблице 1, я думал, что это нормально использовать? Вы говорите о параметре 'internalFormat', правильно? –

+0

Но вы не знаете, что на самом деле означает GL_RED. Это может дать вам «GL_R8». Это может дать вам «GL_R16». Когда вы не выбираете * специальный * формат, вы отказываетесь от права выбора формата. И он перестает работать, когда вы используете 'GL_R8UI', потому что вы, вероятно, не настроили передачу пикселей на [загружать интегральные данные вместо нормализованных поплавков] (http://www.opengl.org/wiki/Pixel_Transfer#Integer_format). –

ответ

13

Ugh. Таким образом, по-видимому, трехмерная текстура должна быть привязана как многоуровневая, иначе шейдер не сможет изменить любую uvw-координату с помощью w> 0.

glBindImageTexture(0, volume_tid, 0, /*layered=*/GL_TRUE, 0, GL_READ_WRITE, GL_R8); 

делает трюк.

+0

danke schön! :) –

+1

Я потерял полдня. Спасибо!!! Я не думаю, что когда-нибудь это сообразил. –

+0

Просто и провел сумасшедшую экскурсию через это. Это было очень запутанно, так как работали над Nvidia GM107, но не GK110b (оба последних драйвера). : - / – FHoenig

Смежные вопросы