// Change the position vector to be 4 units for proper matrix calculations. input.position.w = 1.0f;
// Calculate the position of the vertex against the world, view, and projection matrices. output.position = mul(input.position, worldMatrix); output.position = mul(output.position, viewMatrix); output.position = mul(output.position, projectionMatrix);
// Sample the pixel color from the texture using the sampler at this texture coordinate location. textureColor = shaderTexture.Sample(SampleType, input.tex);
return textureColor; }
Textureshaderclass.h
TextureShaderClass 只是上一教程中 ColorShaderClass 的更新版本,此类将用于使用顶点和像素着色器绘制 3D 模型。
// Set the shader parameters that it will use for rendering. result = SetShaderParameters(deviceContext, worldMatrix, viewMatrix, projectionMatrix, texture); if(!result) { returnfalse; }
// Now render the prepared buffers with the shader. RenderShader(deviceContext, indexCount);
// Compile the vertex shader code. result = D3DCompileFromFile(vsFilename, NULL, NULL, "TextureVertexShader", "vs_5_0", D3D10_SHADER_ENABLE_STRICTNESS, 0, &vertexShaderBuffer, &errorMessage); if(FAILED(result)) { // If the shader failed to compile it should have writen something to the error message. if(errorMessage) { OutputShaderErrorMessage(errorMessage, hwnd, vsFilename); } // If there was nothing in the error message then it simply could not find the shader file itself. else { MessageBox(hwnd, vsFilename, L"Missing Shader File", MB_OK); }
returnfalse; }
// Compile the pixel shader code. result = D3DCompileFromFile(psFilename, NULL, NULL, "TexturePixelShader", "ps_5_0", D3D10_SHADER_ENABLE_STRICTNESS, 0, &pixelShaderBuffer, &errorMessage); if(FAILED(result)) { // If the shader failed to compile it should have writen something to the error message. if(errorMessage) { OutputShaderErrorMessage(errorMessage, hwnd, psFilename); } // If there was nothing in the error message then it simply could not find the file itself. else { MessageBox(hwnd, psFilename, L"Missing Shader File", MB_OK); }
returnfalse; }
// Create the vertex shader from the buffer. result = device->CreateVertexShader(vertexShaderBuffer->GetBufferPointer(), vertexShaderBuffer->GetBufferSize(), NULL, &m_vertexShader); if(FAILED(result)) { returnfalse; }
// Create the pixel shader from the buffer. result = device->CreatePixelShader(pixelShaderBuffer->GetBufferPointer(), pixelShaderBuffer->GetBufferSize(), NULL, &m_pixelShader); if(FAILED(result)) { returnfalse; }
// Create the vertex input layout description. // This setup needs to match the VertexType stucture in the ModelClass and in the shader. polygonLayout[0].SemanticName = "POSITION"; polygonLayout[0].SemanticIndex = 0; polygonLayout[0].Format = DXGI_FORMAT_R32G32B32_FLOAT; polygonLayout[0].InputSlot = 0; polygonLayout[0].AlignedByteOffset = 0; polygonLayout[0].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; polygonLayout[0].InstanceDataStepRate = 0;
// Setup the description of the dynamic matrix constant buffer that is in the vertex shader. matrixBufferDesc.Usage = D3D11_USAGE_DYNAMIC; matrixBufferDesc.ByteWidth = sizeof(MatrixBufferType); matrixBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; matrixBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; matrixBufferDesc.MiscFlags = 0; matrixBufferDesc.StructureByteStride = 0;
// Create the constant buffer pointer so we can access the vertex shader constant buffer from within this class. result = device->CreateBuffer(&matrixBufferDesc, NULL, &m_matrixBuffer); if(FAILED(result)) { returnfalse; }
// Get a pointer to the error message text buffer. compileErrors = (char*)(errorMessage->GetBufferPointer());
// Get the length of the message. bufferSize = errorMessage->GetBufferSize();
// Open a file to write the error message to. fout.open("shader-error.txt");
// Write out the error message. for(i=0; i<bufferSize; i++) { fout << compileErrors[i]; }
// Close the file. fout.close();
// Release the error message. errorMessage->Release(); errorMessage = 0;
// Pop a message up on the screen to notify the user to check the text file for compile errors. MessageBox(hwnd, L"Error compiling shader. Check shader-error.txt for message.", shaderFilename, MB_OK);
// Transpose the matrices to prepare them for the shader. worldMatrix = XMMatrixTranspose(worldMatrix); viewMatrix = XMMatrixTranspose(viewMatrix); projectionMatrix = XMMatrixTranspose(projectionMatrix);
// Lock the constant buffer so it can be written to. result = deviceContext->Map(m_matrixBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); if(FAILED(result)) { returnfalse; }
// Get a pointer to the data in the constant buffer. dataPtr = (MatrixBufferType*)mappedResource.pData;
// Copy the matrices into the constant buffer. dataPtr->world = worldMatrix; dataPtr->view = viewMatrix; dataPtr->projection = projectionMatrix;
// Unlock the constant buffer. deviceContext->Unmap(m_matrixBuffer, 0);
// Set the position of the constant buffer in the vertex shader. bufferNumber = 0;
// Finanly set the constant buffer in the vertex shader with the updated values. deviceContext->VSSetConstantBuffers(bufferNumber, 1, &m_matrixBuffer);
SetShaderParameters 函数已从上一教程中修改,现在包括在像素着色器中设置纹理。
1 2 3 4 5
// Set shader texture resource in the pixel shader. deviceContext->PSSetShaderResources(0, 1, &texture);
returntrue; }
RenderShader 调用着色器技术来渲染多边形。
1 2 3 4 5 6 7 8
voidTextureShaderClass::RenderShader(ID3D11DeviceContext* deviceContext, int indexCount) { // Set the vertex input layout. deviceContext->IASetInputLayout(m_layout);
// Set the vertex and pixel shaders that will be used to render this triangle. deviceContext->VSSetShader(m_vertexShader, NULL, 0); deviceContext->PSSetShader(m_pixelShader, NULL, 0);
RenderShader 函数已更改为在渲染前在像素着色器中设置采样状态。
1 2 3 4 5 6 7 8
// Set the sampler state in the pixel shader. deviceContext->PSSetSamplers(0, 1, &m_sampleState);
// Render the triangle. deviceContext->DrawIndexed(indexCount, 0, 0);
// Open the targa file for reading in binary. error = fopen_s(&filePtr, filename, "rb"); if(error != 0) { returnfalse; }
// Read in the file header. count = (unsignedint)fread(&targaFileHeader, sizeof(TargaHeader), 1, filePtr); if(count != 1) { returnfalse; }
// Get the important information from the header. height = (int)targaFileHeader.height; width = (int)targaFileHeader.width; bpp = (int)targaFileHeader.bpp;
// Check that it is 32 bit and not 24 bit. if(bpp != 32) { returnfalse; }
// Calculate the size of the 32 bit image data. imageSize = width * height * 4;
// Allocate memory for the targa image data. targaImage = newunsignedchar[imageSize]; if(!targaImage) { returnfalse; }
// Read in the targa image data. count = (unsignedint)fread(targaImage, 1, imageSize, filePtr); if(count != imageSize) { returnfalse; }
// Close the file. error = fclose(filePtr); if(error != 0) { returnfalse; }
// Allocate memory for the targa destination data. m_targaData = newunsignedchar[imageSize]; if(!m_targaData) { returnfalse; }
// Initialize the index into the targa destination data array. index = 0;
// Initialize the index into the targa image data. k = (width * height * 4) - (width * 4);
// Now copy the targa image data into the targa destination array in the correct order since the targa format is stored upside down. for(j=0; j<height; j++) { for(i=0; i<width; i++) { m_targaData[index + 0] = targaImage[k + 2]; // Red. m_targaData[index + 1] = targaImage[k + 1]; // Green. m_targaData[index + 2] = targaImage[k + 0]; // Blue m_targaData[index + 3] = targaImage[k + 3]; // Alpha
// Increment the indexes into the targa data. k += 4; index += 4; }
// Set the targa image data index back to the preceding row at the beginning of the column since its reading it in upside down. k -= (width * 8); }
// Release the targa image data now that it was copied into the destination array. delete [] targaImage; targaImage = 0;
// Shutdown the vertex and index buffers. ShutdownBuffers();
return; }
voidModelClass::Render(ID3D11DeviceContext* deviceContext) { // Put the vertex and index buffers on the graphics pipeline to prepare them for drawing. RenderBuffers(deviceContext);
// Load the index array with data. indices[0] = 0; // Bottom left. indices[1] = 1; // Top middle. indices[2] = 2; // Bottom right.
// Set up the description of the static vertex buffer. vertexBufferDesc.Usage = D3D11_USAGE_DEFAULT; vertexBufferDesc.ByteWidth = sizeof(VertexType) * m_vertexCount; vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; vertexBufferDesc.CPUAccessFlags = 0; vertexBufferDesc.MiscFlags = 0; vertexBufferDesc.StructureByteStride = 0;
// Give the subresource structure a pointer to the vertex data. vertexData.pSysMem = vertices; vertexData.SysMemPitch = 0; vertexData.SysMemSlicePitch = 0;
// Now create the vertex buffer. result = device->CreateBuffer(&vertexBufferDesc, &vertexData, &m_vertexBuffer); if(FAILED(result)) { returnfalse; }
// Set up the description of the static index buffer. indexBufferDesc.Usage = D3D11_USAGE_DEFAULT; indexBufferDesc.ByteWidth = sizeof(unsignedlong) * m_indexCount; indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; indexBufferDesc.CPUAccessFlags = 0; indexBufferDesc.MiscFlags = 0; indexBufferDesc.StructureByteStride = 0;
// Give the subresource structure a pointer to the index data. indexData.pSysMem = indices; indexData.SysMemPitch = 0; indexData.SysMemSlicePitch = 0;
// Create the index buffer. result = device->CreateBuffer(&indexBufferDesc, &indexData, &m_indexBuffer); if(FAILED(result)) { returnfalse; }
// Release the arrays now that the vertex and index buffers have been created and loaded. delete [] vertices; vertices = 0;
delete [] indices; indices = 0;
returntrue; }
voidModelClass::ShutdownBuffers() { // Release the index buffer. if(m_indexBuffer) { m_indexBuffer->Release(); m_indexBuffer = 0; }
// Set vertex buffer stride and offset. stride = sizeof(VertexType); offset = 0; // Set the vertex buffer to active in the input assembler so it can be rendered. deviceContext->IASetVertexBuffers(0, 1, &m_vertexBuffer, &stride, &offset);
// Set the index buffer to active in the input assembler so it can be rendered. deviceContext->IASetIndexBuffer(m_indexBuffer, DXGI_FORMAT_R32_UINT, 0);
// Set the type of primitive that should be rendered from this vertex buffer, in this case triangles. deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
boolGraphicsClass::Initialize(int screenWidth, int screenHeight, HWND hwnd) { bool result;
// Create the Direct3D object. m_Direct3D = new D3DClass; if(!m_Direct3D) { returnfalse; }
// Initialize the Direct3D object. result = m_Direct3D->Initialize(screenWidth, screenHeight, VSYNC_ENABLED, hwnd, FULL_SCREEN, SCREEN_DEPTH, SCREEN_NEAR); if(!result) { MessageBox(hwnd, L"Could not initialize Direct3D.", L"Error", MB_OK); returnfalse; }
// Create the camera object. m_Camera = new CameraClass; if (!m_Camera) { returnfalse; }
// Set the initial position of the camera. m_Camera->SetPosition(0.0f, 0.0f, -5.0f);
// Create the model object. m_Model = new ModelClass; if (!m_Model) { returnfalse; }
ModelClass:Initialize 函数现在接受将用于渲染模型的纹理的名称。
1 2 3 4 5 6 7
// Initialize the model object. result = m_Model->Initialize(m_Direct3D->GetDevice(), m_Direct3D->GetDeviceContext(), "../Engine/data/stone01.tga"); if (!result) { MessageBox(hwnd, L"Could not initialize the model object.", L"Error", MB_OK); returnfalse; }
// Create the texture shader object. m_TextureShader = new TextureShaderClass; if (!m_TextureShader) { returnfalse; }
// Initialize the color shader object. result = m_TextureShader->Initialize(m_Direct3D->GetDevice(), hwnd); if (!result) { MessageBox(hwnd, L"Could not initialize the color shader object.", L"Error", MB_OK); returnfalse; }
// Clear the buffers to begin the scene. m_Direct3D->BeginScene(0.0f, 0.0f, 0.0f, 1.0f);
// Generate the view matrix based on the camera's position. m_Camera->Render();
// Get the world, view, and projection matrices from the camera and d3d objects. m_Direct3D->GetWorldMatrix(worldMatrix); m_Camera->GetViewMatrix(viewMatrix); m_Direct3D->GetProjectionMatrix(projectionMatrix);
// Put the model vertex and index buffers on the graphics pipeline to prepare them for drawing. m_Model->Render(m_Direct3D->GetDeviceContext());
// Render the model using the texture shader. result = m_TextureShader->Render(m_Direct3D->GetDeviceContext(), m_Model->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix, m_Model->GetTexture()); if (!result) { returnfalse; }
// Present the rendered scene to the screen. m_Direct3D->EndScene();