Программные интерфейсы DirectX 11 и OpenGL 4

64 downloads 129230 Views 4MB Size Report
План лекции. • API и Hardware. • Графический конвейер и шейдеры. • Связь с предыдущей лекции. • Простой сэмпл. • Идеология DX и GL. • Особенности ...
Программные интерфейсы DirectX 11 и OpenGL 4 Advanced CG course, 2012

План лекции • API и Hardware • Графический конвейер и шейдеры • Связь с предыдущей лекции • Простой сэмпл

• Идеология DX и GL • Особенности программной реализации • Объекты и сущности DX и GL • DX Compute Shaders vs CUDA • Простой пример • Создание ресурсов • Привязка ресурсов к шейдерам • Эффекты в DX • Отладка и поиск ошибок • Аналоги механизма ООП

API программирования GPU • Графика • Вычисления общего назначения

API и Hardware • API: • DX9, DX10, OpenGL 1.0, OpenGL 2.0 • DX11, (OpenGL 3.0 & OpenGL 4.0) • Pipeline • Fixed Function Pipeline (DX7, OpenGL 1.0) • DX9 Pipeline (OpenGL 2.0+) • DX10 Pipeline (OpenGL 3.0+) • DX11 Pipeline (OpenGL 4.0+) • Hardware • DX7 hardware • DX8 hardware • DX9 hardware • DX10 hardware • DX11 hardware

Hardware, Pipeline и DirectX • Прямое соответствие • Фиксированный конвейер

• DX7 hardware = FFP. • Программируемый конвейер.

• DX10 hardware = VS-GS-PS;

GL 2.0 GL 3.0

• DX11 hardware = VS-HS-DS-GS-PS;

GL 4.0

• DX9 hardware = VS-PS;

DX11

GL 1.0

Как выбрать API? • На ОС какого типа должна работать моя программа? • Windows => DX или GL • Linux/Android => GL • MacOS => GL • На каком железе должна работать моя программа? • DX11 hardware => DX11 || GL 4.0 • DX10 hardware => DX11 || GL 3.0 • DX9 hardware => DX11 || DX9 (WinXP) || GL 2.0 • Везде => GL 1.0 || DX11 ()

Графичеcкий конвейер и шейдеры Vertex attribute fetch Resources (constants, textures, buffers)

Input Assembler vertex attributes tex fetches

Vertex Shader vs_output indices

struct VS_INPUT { float4 position : POSITION; float3 normal : NORMAL; float2 texCoord : TEXCOORD; float3 tangent : TANGENT; };

Primitive Assembly vs_output

Rasterizer

Early depth & stencil test

vs_output (interpolated) tex fetches

Pixel Shader render to texture

ps_output

Output Merger color

screen

Late depth test

GPU это

GPU это большой конвейер

GPU это большой конвейер

Как это использовать • Загрузка текста шейдеров из файла • Компиляция • Линковка

• Создание и загрузка данных • Привязка ресурсов • Draw call

Создание объекта программы в GL

Ray Marching на GL3 • http://courses.graphicon.ru/main/cg/2011/assigns/4

Ray Marching на GL3 • http://courses.graphicon.ru/main/cg/2011/assigns/4

Ray Marching на GL3 • http://courses.graphicon.ru/main/cg/2011/assigns/4

Ray Marching на GL3 • http://courses.graphicon.ru/main/cg/2011/assigns/4

Full screen quad на GL3 • http://courses.graphicon.ru/main/cg/2011/assigns/4

Full screen quad на GL3 std::ifstream vertSourceFile("../main/Vertex.vert"); std::ifstream fragSourceFile("../main/Fragment.frag"); std::string fragSource; std::string vertSource; … const char* tmpVertSource = vertSource.c_str(); const char* tmpFragSource = fragSource.c_str(); if (!glusBuildProgram(&g_program, &tmpVertSource, 0, 0, 0, &tmpFragSource)) throw std::runtime_error("shader compilation failed!");

Full screen quad на GL3 • glusBuildProgram(...)

Full screen quad на GL3 struct GLUSshaderprogram { GLUSuint program; GLUSuint vertex; GLUSuint control; GLUSint evaluation; GLUSuint geometry; GLUSuint fragment; };

Full screen quad на GL3 • g_pFullScreenQuad = new FullScreenQuad();

Full screen quad на GL3 • g_pFullScreenQuad = new FullScreenQuad();

float quadPos[] = { -1.0f, 1.0f, // v0 - top left corner -1.0f, -1.0f, // v1 - bottom left corner 1.0f, 1.0f, // v2 - top right corner 1.0f, -1.0f // v3 - bottom right corner }; m_vertexBufferObject = 0; m_vertexLocation = 0;

Full screen quad на GL3 • g_pFullScreenQuad = new FullScreenQuad();

Vertex Shader (1)

Full screen quad на GL3 glUseProgram(g_program.program); setUniform(g_program.program, "g_screenWidth", g_width); setUniform(g_program.program, "g_screenHeight", g_height); ... setUniform(g_program.program, "g_bgColor", float4(0,0,1,0)); glDisable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); glViewport(0, 0, g_width, g_height); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); g_pFullScreenQuad->Draw();

Full screen quad на GL3 • g_pFullScreenQuad->Draw();

void FullScreenQuad::Draw() { glBindVertexArray(m_vertexArrayObject); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); }

Full screen quad на GL3 #version 330 in vec2 vertex; out vec2 fragmentTexCoord; void main(void) { fragmentTexCoord = vertex * 0.5 + 0.5; // [-1,1]-> [0,1] gl_Position = vec4(vertex, 0.0, 1.0); }

Full screen quad на GL3 #version 330 in vec2 fragmentTexCoord; out vec4 fragColor; void main(void) { fragColor = vec4(1,0,0,0); }

Реализации 4 задания

Реализации 4 задания

Графичеcкий конвейер и шейдеры Vertex attribute fetch Resources (constants, textures, buffers)

Input Assembler vertex attributes tex fetches

Vertex Shader vs_output indices

struct VS_INPUT { float4 position : POSITION; float3 normal : NORMAL; float2 texCoord : TEXCOORD; float3 tangent : TANGENT; };

Primitive Assembly vs_output

Rasterizer

Early depth & stencil test

vs_output (interpolated) tex fetches

Pixel Shader render to texture

ps_output

Output Merger color

screen

Late depth test

DirectX • API для доступа к функциональности GPU • ОС Windows и • Преимущественно С/C++, но

• COM (Component Object Model)/DLL • Для С# есть Managed DirectX

• Хотите использовать DX в вашем любимом ЯП? • Реализуйте поддержку COM объектов • http://www.rsdn.ru/article/com/introcom.xml

• Жесткая спецификация стандарта (DX9, DX10, DX11) • Каждая новая версия несовместима с предыдущей!

OpenGL • API для доступа к функциональности GPU • Мультиплатформенный • Мультиязыковой • Процедурный • Динамически расширяемый • Указатели на функции • wglGetProcAdress(…) • Доступ к объектам осуществляется при помощи

целочисленный имен • Понятие текущего объекта

glGenBuffers (1, &m_vbo); glBindBuffer(GL_ARRAY_BUFFER, m_vbo); glBufferData(…);

Объекты и сущности • Устройство (только в DX) • Контекст • VAO (Input Layout в DX) • Шейдеры • Буферы (VBO, PBO) • Текстуры • FBO (RTV в DX) • Sampler • *Image (UAV) • Состояния

*glBindImageTexture Image объекта нет

• Специальные объекты (много в OGL) • (типа Transform Feedback-Object, program-pipeline)

Объекты и сущности • Устройство (только в DX) • Контекст • VAO (Input Layout в DX) • Шейдеры • Буферы (VBO, PBO) • Текстуры • FBO (RTV в DX) • Sampler • *Image (UAV) • Состояния

*glBindImageTexture Image объекта нет

• Специальные объекты (много в OGL) • (типа Transform Feedback-Object, program-pipeline)

Transform feedback object

Stream Out & Transform feedback

Stream Out & Transform feedback • Работает как операция Append • В CUDA для этого необходимо делать scan • (префиксная сумма)

Константы • GL • Uniform переменные (uniform float3 lightDirection;) • UBO

На CPU:

float data[3] = {0.5f, 1.0f, 0.1f}; GLint location = glGetUniformLocation(a_program, “lightDirection”); if(location >= 0) glUniform3fv(location, 1, data); • DX11 • Константные буфера (= UBO в GL) • Эффекты упрощают жизнь (доступ к переменным по именам) cbuffer cbLights { float4 vLightColor[3] = {{1,0,0,0},{0,1,0,0},{0,0,1,0}}; float4 vLightPosition[3]; };

VS

CUDA Hello World

CUDA VectorAdd (CUDA_SDK) float* h_A = (float*)malloc(size); float* h_B = (float*)malloc(size); float* h_C = (float*)malloc(size); // Initialize input vectors RandomInit(h_A, N); RandomInit(h_B, N); // Allocate vectors in device memory cudaMalloc((void**)&d_A, size); cudaMalloc((void**)&d_B, size); cudaMalloc((void**)&d_C, size); // Copy vectors from host memory to device memory cudaMemcpy(d_A, h_A, size, cudaMemcpyHostToDevice); cudaMemcpy(d_B, h_B, size, cudaMemcpyHostToDevice); // Invoke kernel int threadsPerBlock = 256; int blocksPerGrid = (N + threadsPerBlock - 1) / threadsPerBlock; VecAdd(d_A, d_B, d_C, N);

// Copy result from device memory to host memory // h_C contains the result in host memory cudaMemcpy(h_C, d_C, size, cudaMemcpyDeviceToHost);

BasicCompute11

BasicCompute11

+ 500 строк С++ кода!

Привязка ресурсов к шейдерам • Ресурсы • Буферы • Текстуры • Константные буферы и константы • Шейдеры • Вершинные • Hull (Tesselation) • Domain (Evaluation) • Геометрические • Фрагментные (пиксельные) • Вычислительные (Compute Shaders, только в DX)

Привязка текстур в DX • Shader Resource View (SRV + Sampler) • Unordered Access View (UAV) • Render Target (RTV + DSV) • Render Target View • Depth Stencil View

Эффекты в DX • • • • •

Надстройка над DX, предоставляемая MS c DXSDK Свой компилятор Позволяет строить графический конвейер Определять sampler state, blend state, rasterizer state Позволяет обращаться к переменным по именам

technique11 RenderCubeMap { pass p0 { SetVertexShader (CompileShader(vs_5_0, VS_CubeMap())); SetHullShader(NULL); SetDomainShader(NULL); SetGeometryShader (CompileShader(gs_5_0, GS_CubeMap())); SetPixelShader (CompileShader(ps_5_0, PS_CubeMap())); SetBlendState (NoBlend, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF ); } };

Привязка текстур в GL void bindTexture (GLuint program, GLint unit, const GLchar *name, GLuint texture) { glActiveTexture (GL_TEXTURE0 + unit); glBindTexture (GL_TEXTURE_2D, texture); GLint location = glGetUniformLocation (program, name); if(location >=0) glUniform1i(location, unit); }

Привязка текстур в GL

OGL4 Sampler Object

Привязка тестур в GL • Отличия в 3 и 4 версии

Привязка тестур в GL • Отличия в 3 и 4 версии

OGL4 Sampler Object • В OGL3 текстуры и сэмплеры не разделены • В OGL4 добавлен объект “Sampler”

glGenSamplers (1, &s_id); glSamplerParameteri (s_id, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glSamplerParameteri (s_id, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glSamplerParameteri (s_id, GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE) ….. ….. glActiveTexture (GL_TEXTURE0 + unit); glBindSampler (unit, g_gaussSampler);

Текстурная фильтрация

Текстурная филтрация • Билинейная

Текстурная фильтрация

Текстурная фильтрация • Mip-Map уровни

Билинейная фильтрация

Трилинейная фильтрация

Анизотропная филтрация

Трилинейная фильтрация • Интерполяция между mip уровнями

Текстурная фильтрация • Анизотропная

Текстурная фильтрация в GL glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, ); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, );

• When the second parameter is GL_TEXTURE_MIN_FILTER,

parameter three can be: • GL_NEAREST_MIPMAP_NEAREST • GL_LINEAR_MIPMAP_NEAREST • GL_NEAREST_MIPMAP_LINEAR • GL_LINEAR_MIPMAP_LINEAR • GL_NEAREST • GL_LINEAR

• When the second parameter is GL_TEXTURE_MAG_FILTER,

parameter three can be: • GL_LINEAR • GL_NEAREST

Текстурная фильтрация в DX • В коде шейдера (Эффекты) SamplerState g_samLinear { Filter = MIN_MAG_MIP_LINEAR; AddressU = Clamp; AddressV = Clamp; }; ... float4 vDiffuse = g_txDiffuse.Sample( g_samLinear, Input.vTexcoord );

• Или на CPU, но не в SRV ID3D11SamplerState* m_pSamLinear; pd3dDeviceContext->PSSetSamplers( 0, 1, &m_pSamLinear ); pd3dDeviceContext->PSSetSamplers( 1, 1, &m_pSamLinear );

Как выбирается мип-уровень? void main() { vec4 firstData = texture(someSampler, textureCoords); vec2 otherTexDx = dFdx(otherTexCoords); vec2 otherTexDy = dFdy(otherTexCoords); if (parameterValue < 20) { firstData += textureGrad(someOtherSampler, otherTexCoords, otherTexDx, otherTexDy); } }

Рендеринг в текстуру • OpenGL Frame Buffer Object (FBO)

Рендеринг в текстуру Texture1

Texture2

Shader

FBO

Texture2

Out_Texture1

Out_Texture2

Depth buffer1

Depth buffer2

Отладка в DirectX • DirectX Debug Layer

Отладка в DirectX • Nsight

Отладка в OpenGL • glGetError() • Удобно использовать макрос типа CHECK_GL_ERROR • Предположим glTexImage2D сгенерировала ошибку • GL_INVALID_VALUE

Отладка в OpenGL • gDebugger

Разработка сложных шейдеров • DirectX11 “Dynamic Shader Linkage” • OpenGL4 “Subroutine” • Аналог виртуальных функций, но (!!!) • Это не виртуальные функции!

OpenGL subroutine #version 400 subroutine vec3 shadeModelType( vec4 position, vec3 normal); subroutine uniform shadeModelType shadeModel; subroutine ( shadeModelType ) vec3 phongModel( vec4 position, vec3 norm ) { // The ADS shading calculations go here (see: "Using // functions in shaders," and "Implementing // per-vertex ambient, diffuse and specular (ADS) shading") … } subroutine ( shadeModelType ) vec3 diffuseOnly( vec4 position, vec3 norm ) { vec3 s = normalize( vec3(Light.Position - position) ); return Light.Ld * Material.Kd * max( dot(s, norm), 0.0 ); }

OpenGL subroutine void main() { vec3 eyeNorm; vec4 eyePosition; // Get the position and normal in eye space getEyeSpace(eyeNorm, eyePosition);

// Evaluate the shading equation. This will call one of // the functions: diffuseOnly or phongModel LightIntensity = shadeModel( eyePosition, eyeNorm ); gl_Position = MVP * vec4(VertexPosition,1.0); }

OpenGL subroutine glUseProgram (programHandle); GLuint adsIndex = glGetSubroutineIndex(programHandle, GL_VERTEX_SHADER,"phongModel"); GLuint diffuseIndex = glGetSubroutineIndex(programHandle, GL_VERTEX_SHADER, "diffuseOnly");

glUniformSubroutinesuiv( GL_VERTEX_SHADER, 1, &adsIndex); ... // Render the left teapot glUniformSubroutinesuiv( GL_VERTEX_SHADER, 1, &diffuseIndex); ... // Render the right teapot

DX11 Dynamic Shader Linkage • Почти то же самое, но линкуем сразу класс

interface iBaseLight { float3 IlluminateAmbient (float3 vNormal); float3 IlluminateDiffuse (float3 vNormal); float3 IlluminateSpecular(float3 vNormal, int specularPower ); };

// ... interface iBaseMaterial { float3 GetAmbientColor(float2 vTexcoord); float3 GetDiffuseColor (float2 vTexcoord); int GetSpecularPower(); };

DX11 Dynamic Shader Linkage • Почти то же самое, но линкуем сразу класс

class cAmbientLight : iBaseLight { float3 m_vLightColor; bool m_bEnable; float3 IlluminateAmbient (float3 vNormal); float3 IlluminateDiffuse (float3 vNormal); float3 IlluminateSpecular(float3 vNormal, int specularPower ); }; class cBaseMaterial : iBaseMaterial { float3 m_vColor; int m_iSpecPower; float3 GetAmbientColor (float2 vTexcoord); float3 GetDiffuseColor (float2 vTexcoord); int GetSpecularPower(); };

DX11 Dynamic Shader Linkage iBaseLight g_abstractAmbientLighting; iBaseLight g_abstractDirectLighting; iBaseMaterial g_abstractMaterial; float4 PSMain ( PS_INPUT Input ) : SV_TARGET { // Compute the Ambient term float3 Ambient = g_abstractMaterial.GetAmbientColor( Input.vTexcoord ) * g_abstractAmbientLighting.IlluminateAmbient( Input.vNormal ); // Accumulate the Diffuse contribution float3 Diffuse = g_abstractMaterial.GetDiffuseColor( Input.vTexcoord ) * g_abstractDirectLighting.IlluminateDiffuse( Input.vNormal ); // Compute the Specular contribution float3 Specular = g_abstractDirectLighting.IlluminateSpecular( Input.vNormal, g_abstractMaterial.GetSpecularPower() ); // Accumulate the lighting with saturation float3 Lighting = saturate( Ambient + Diffuse + Specular ); return float4(Lighting,1.0f); }

Ссылки • DirectX 11 • MS DirectX SDK (http://msdn.microsoft.com/directx) • http://geekswithblogs.net/JoshReuben/archive/2012/03/14/d3d-11programming-in-a-nutshell.aspx (краткий справочник) • OpenGL 3.0+ • http://steps3d.narod.ru • http://www.gamedev.ru/community/ogl/ • http://nopper.tv/opengl.html • http://www.arcsynthesis.org/gltut/

Задание