3D Convolution with CUDA using shared memory - c++
I'm currently trying to adapt the 2D convolution code from THIS question to 3D and having trouble trying to understand where my error is.
My 2D Code looks like this:
#include <iostream>
#define MASK_WIDTH 3
#define MASK_RADIUS MASK_WIDTH / 2
#define TILE_WIDTH 8
#define W (TILE_WIDTH + MASK_WIDTH - 1)
/**
* GPU 2D Convolution using shared memory
*/
__global__ void convolution(float *I, float* M, float *P, int width, int height)
{
/***** WRITE TO SHARED MEMORY *****/
__shared__ float N_ds[W][W];
// First batch loading
int dest = threadIdx.x + (threadIdx.y * TILE_WIDTH);
int destY = dest / W;
int destX = dest % W;
int srcY = destY + (blockIdx.y * TILE_WIDTH) - MASK_RADIUS;
int srcX = destX + (blockIdx.x * TILE_WIDTH) - MASK_RADIUS;
int src = srcX + (srcY * width);
if(srcY >= 0 && srcY < height && srcX >= 0 && srcX < width)
N_ds[destY][destX] = I[src];
else
N_ds[destY][destX] = 0;
// Second batch loading
dest = threadIdx.x + (threadIdx.y * TILE_WIDTH) + TILE_WIDTH * TILE_WIDTH;
destY = dest / W;
destX = dest % W;
srcY = destY + (blockIdx.y * TILE_WIDTH) - MASK_RADIUS;
srcX = destX + (blockIdx.x * TILE_WIDTH) - MASK_RADIUS;
src = srcX + (srcY * width);
if(destY < W)
{
if(srcY >= 0 && srcY < height && srcX >= 0 && srcX < width)
N_ds[destY][destX] = I[src];
else
N_ds[destY][destX] = 0;
}
__syncthreads();
/***** Perform Convolution *****/
float sum = 0;
int y;
int x;
for(y = 0; y < MASK_WIDTH; y++)
for(x = 0; x < MASK_WIDTH; x++)
sum = sum + N_ds[threadIdx.y + y][threadIdx.x + x] * M[x + (y * MASK_WIDTH)];
y = threadIdx.y + (blockIdx.y * TILE_WIDTH);
x = threadIdx.x + (blockIdx.x * TILE_WIDTH);
if(y < height && x < width)
P[x + (y * width)] = sum;
__syncthreads();
}
int main(int argc, char* argv[])
{
int image_width = 16;
int image_height = 16;
float *deviceInputImageData;
float *deviceOutputImageData;
float *deviceMaskData;
float data[] =
{
1.0f, 1.0f, 1.0f, 1.0f, 3.0f, 1.0f, 5.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
2.0f, 2.0f, 2.0f, 2.0f, 1.0f, 4.0f, 1.0f, 6.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
3.0f, 3.0f, 3.0f, 1.0f, 3.0f, 1.0f, 5.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
4.0f, 4.0f, 4.0f, 2.0f, 1.0f, 4.0f, 1.0f, 6.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
5.0f, 5.0f, 5.0f, 1.0f, 3.0f, 1.0f, 5.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
6.0f, 6.0f, 6.0f, 2.0f, 1.0f, 4.0f, 1.0f, 6.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
7.0f, 7.0f, 7.0f, 1.0f, 3.0f, 1.0f, 5.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
8.0f, 8.0f, 8.0f, 2.0f, 1.0f, 4.0f, 1.0f, 6.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
9.0f, 9.0f, 9.0f, 1.0f, 3.0f, 1.0f, 5.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
10.0f, 10.0f, 10.0f, 2.0f, 1.0f, 4.0f, 1.0f, 6.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
11.0f, 11.0f, 11.0f, 1.0f, 3.0f, 1.0f, 5.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
12.0f, 12.0f, 12.0f, 2.0f, 1.0f, 4.0f, 1.0f, 6.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
13.0f, 13.0f, 13.0f, 1.0f, 3.0f, 1.0f, 5.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
14.0f, 14.0f, 14.0f, 2.0f, 1.0f, 4.0f, 1.0f, 6.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
15.0f, 15.0f, 15.0f, 1.0f, 3.0f, 1.0f, 5.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
16.0f, 16.0f, 16.0f, 2.0f, 1.0f, 4.0f, 1.0f, 6.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f
};
float mask[] =
{
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f
};
// CHECK CHECK CHECK CHECK CHECK
int shared_memory_size = W * W;
int block_size = TILE_WIDTH * TILE_WIDTH;
int max_size = 2 * block_size;
std::cout << "Block Size: " << block_size << " - Shared Memory Size: " << shared_memory_size << " - Max Size: " << max_size << std::endl;
std::cout << "SHARED MEMORY SIZE HAS TO BE SMALLER THAN MAX SIZE IN ORDER TO WORK PROPERLY !!!!!!!";
cudaMalloc((void **)&deviceInputImageData, image_width * image_height * sizeof(float));
cudaMalloc((void **)&deviceOutputImageData, image_width * image_height * sizeof(float));
cudaMalloc((void **)&deviceMaskData, MASK_WIDTH * MASK_WIDTH * sizeof(float));
cudaMemcpy(deviceInputImageData, data, image_width * image_height * sizeof(float), cudaMemcpyHostToDevice);
cudaMemcpy(deviceMaskData, mask, MASK_WIDTH * MASK_WIDTH * sizeof(float), cudaMemcpyHostToDevice);
dim3 dimBlock(TILE_WIDTH, TILE_WIDTH, 1);
dim3 dimGrid((image_width + TILE_WIDTH - 1) / TILE_WIDTH, (image_height + TILE_WIDTH - 1) / TILE_WIDTH);
convolution<<<dimGrid, dimBlock>>>(deviceInputImageData, deviceMaskData, deviceOutputImageData, image_width, image_height);
cudaDeviceSynchronize();
cudaMemcpy(data, deviceOutputImageData, image_width * image_height * sizeof(float), cudaMemcpyDeviceToHost);
// Print data
for(int i = 0; i < image_width * image_height; ++i)
{
if(i % image_width == 0)
{
std::cout << std::endl;
}
std::cout << data[i] << " - ";
}
cudaFree(deviceInputImageData);
cudaFree(deviceOutputImageData);
cudaFree(deviceMaskData);
return 0;
}
And the 3D equivalent:
#include <iostream>
#define MASK_WIDTH 3
#define MASK_RADIUS MASK_WIDTH / 2
#define TILE_WIDTH 8
#define W (TILE_WIDTH + MASK_WIDTH - 1)
/**
* GPU 2D Convolution using shared memory
*/
__global__ void convolution(float *I, float* M, float *P, int width, int height, int depth)
{
/***** WRITE TO SHARED MEMORY *****/
__shared__ float N_ds[W][W][W];
// First batch loading
int dest = threadIdx.x + (threadIdx.y * TILE_WIDTH) + (threadIdx.z * TILE_WIDTH * TILE_WIDTH);
int destTmp = dest;
int destX = destTmp % W;
destTmp = destTmp / W;
int destY = destTmp % W;
destTmp = destTmp / W;
int destZ = destTmp;
int srcZ = destZ + (blockIdx.z * TILE_WIDTH) - MASK_RADIUS;
int srcY = destY + (blockIdx.y * TILE_WIDTH) - MASK_RADIUS;
int srcX = destX + (blockIdx.x * TILE_WIDTH) - MASK_RADIUS;
int src = srcX + (srcY * width) + (srcZ * width * height);
if(srcZ >= 0 && srcZ < depth && srcY >= 0 && srcY < height && srcX >= 0 && srcX < width)
N_ds[destZ][destY][destX] = I[src];
else
N_ds[destZ][destY][destX] = 0;
// Second batch loading
dest = threadIdx.x + (threadIdx.y * TILE_WIDTH) + (threadIdx.z * TILE_WIDTH * TILE_WIDTH) + TILE_WIDTH * TILE_WIDTH;
destTmp = dest;
destX = destTmp % W;
destTmp = destTmp / W;
destY = destTmp % W;
destTmp = destTmp / W;
destZ = destTmp;
srcZ = destZ + (blockIdx.z * TILE_WIDTH) - MASK_RADIUS;
srcY = destY + (blockIdx.y * TILE_WIDTH) - MASK_RADIUS;
srcX = destX + (blockIdx.x * TILE_WIDTH) - MASK_RADIUS;
src = srcX + (srcY * width) + (srcZ * width * height);
if(destZ < W)
{
if(srcZ >= 0 && srcZ < depth && srcY >= 0 && srcY < height && srcX >= 0 && srcX < width)
N_ds[destZ][destY][destX] = I[src];
else
N_ds[destZ][destY][destX] = 0;
}
__syncthreads();
/***** Perform Convolution *****/
float sum = 0;
int z;
int y;
int x;
for(z = 0; z < MASK_WIDTH; z++)
for(y = 0; y < MASK_WIDTH; y++)
for(x = 0; x < MASK_WIDTH; x++)
sum = sum + N_ds[threadIdx.z + z][threadIdx.y + y][threadIdx.x + x] * M[x + (y * MASK_WIDTH) + (z * MASK_WIDTH * MASK_WIDTH)];
z = threadIdx.z + (blockIdx.z * TILE_WIDTH);
y = threadIdx.y + (blockIdx.y * TILE_WIDTH);
x = threadIdx.x + (blockIdx.x * TILE_WIDTH);
if(z < depth && y < height && x < width)
P[x + (y * width) + (z * width * height)] = sum;
__syncthreads();
}
int main(int argc, char* argv[])
{
int image_width = 16;
int image_height = 16;
int image_depth = 5;
float *deviceInputImageData;
float *deviceOutputImageData;
float *deviceMaskData;
float data[] =
{
1.0f, 1.0f, 1.0f, 1.0f, 3.0f, 1.0f, 5.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
2.0f, 2.0f, 2.0f, 2.0f, 1.0f, 4.0f, 1.0f, 6.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
3.0f, 3.0f, 3.0f, 1.0f, 3.0f, 1.0f, 5.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
4.0f, 4.0f, 4.0f, 2.0f, 1.0f, 4.0f, 1.0f, 6.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
5.0f, 5.0f, 5.0f, 1.0f, 3.0f, 1.0f, 5.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
6.0f, 6.0f, 6.0f, 2.0f, 1.0f, 4.0f, 1.0f, 6.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
7.0f, 7.0f, 7.0f, 1.0f, 3.0f, 1.0f, 5.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
8.0f, 8.0f, 8.0f, 2.0f, 1.0f, 4.0f, 1.0f, 6.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
9.0f, 9.0f, 9.0f, 1.0f, 3.0f, 1.0f, 5.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
10.0f, 10.0f, 10.0f, 2.0f, 1.0f, 4.0f, 1.0f, 6.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
11.0f, 11.0f, 11.0f, 1.0f, 3.0f, 1.0f, 5.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
12.0f, 12.0f, 12.0f, 2.0f, 1.0f, 4.0f, 1.0f, 6.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
13.0f, 13.0f, 13.0f, 1.0f, 3.0f, 1.0f, 5.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
14.0f, 14.0f, 14.0f, 2.0f, 1.0f, 4.0f, 1.0f, 6.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
15.0f, 15.0f, 15.0f, 1.0f, 3.0f, 1.0f, 5.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
16.0f, 16.0f, 16.0f, 2.0f, 1.0f, 4.0f, 1.0f, 6.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f, 3.0f, 1.0f, 5.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
2.0f, 2.0f, 2.0f, 2.0f, 1.0f, 4.0f, 1.0f, 6.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
3.0f, 3.0f, 3.0f, 1.0f, 3.0f, 1.0f, 5.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
4.0f, 4.0f, 4.0f, 2.0f, 1.0f, 4.0f, 1.0f, 6.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
5.0f, 5.0f, 5.0f, 1.0f, 3.0f, 1.0f, 5.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
6.0f, 6.0f, 6.0f, 2.0f, 1.0f, 4.0f, 1.0f, 6.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
7.0f, 7.0f, 7.0f, 1.0f, 3.0f, 1.0f, 5.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
8.0f, 8.0f, 8.0f, 2.0f, 1.0f, 4.0f, 1.0f, 6.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
9.0f, 9.0f, 9.0f, 1.0f, 3.0f, 1.0f, 5.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
10.0f, 10.0f, 10.0f, 2.0f, 1.0f, 4.0f, 1.0f, 6.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
11.0f, 11.0f, 11.0f, 1.0f, 3.0f, 1.0f, 5.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
12.0f, 12.0f, 12.0f, 2.0f, 1.0f, 4.0f, 1.0f, 6.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
13.0f, 13.0f, 13.0f, 1.0f, 3.0f, 1.0f, 5.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
14.0f, 14.0f, 14.0f, 2.0f, 1.0f, 4.0f, 1.0f, 6.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
15.0f, 15.0f, 15.0f, 1.0f, 3.0f, 1.0f, 5.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
16.0f, 16.0f, 16.0f, 2.0f, 1.0f, 4.0f, 1.0f, 6.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f, 3.0f, 1.0f, 5.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
2.0f, 2.0f, 2.0f, 2.0f, 1.0f, 4.0f, 1.0f, 6.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
3.0f, 3.0f, 3.0f, 1.0f, 3.0f, 1.0f, 5.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
4.0f, 4.0f, 4.0f, 2.0f, 1.0f, 4.0f, 1.0f, 6.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
5.0f, 5.0f, 5.0f, 1.0f, 3.0f, 1.0f, 5.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
6.0f, 6.0f, 6.0f, 2.0f, 1.0f, 4.0f, 1.0f, 6.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
7.0f, 7.0f, 7.0f, 1.0f, 3.0f, 1.0f, 5.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
8.0f, 8.0f, 8.0f, 2.0f, 1.0f, 4.0f, 1.0f, 6.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
9.0f, 9.0f, 9.0f, 1.0f, 3.0f, 1.0f, 5.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
10.0f, 10.0f, 10.0f, 2.0f, 1.0f, 4.0f, 1.0f, 6.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
11.0f, 11.0f, 11.0f, 1.0f, 3.0f, 1.0f, 5.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
12.0f, 12.0f, 12.0f, 2.0f, 1.0f, 4.0f, 1.0f, 6.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
13.0f, 13.0f, 13.0f, 1.0f, 3.0f, 1.0f, 5.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
14.0f, 14.0f, 14.0f, 2.0f, 1.0f, 4.0f, 1.0f, 6.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
15.0f, 15.0f, 15.0f, 1.0f, 3.0f, 1.0f, 5.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
16.0f, 16.0f, 16.0f, 2.0f, 1.0f, 4.0f, 1.0f, 6.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f, 3.0f, 1.0f, 5.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
2.0f, 2.0f, 2.0f, 2.0f, 1.0f, 4.0f, 1.0f, 6.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
3.0f, 3.0f, 3.0f, 1.0f, 3.0f, 1.0f, 5.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
4.0f, 4.0f, 4.0f, 2.0f, 1.0f, 4.0f, 1.0f, 6.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
5.0f, 5.0f, 5.0f, 1.0f, 3.0f, 1.0f, 5.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
6.0f, 6.0f, 6.0f, 2.0f, 1.0f, 4.0f, 1.0f, 6.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
7.0f, 7.0f, 7.0f, 1.0f, 3.0f, 1.0f, 5.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
8.0f, 8.0f, 8.0f, 2.0f, 1.0f, 4.0f, 1.0f, 6.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
9.0f, 9.0f, 9.0f, 1.0f, 3.0f, 1.0f, 5.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
10.0f, 10.0f, 10.0f, 2.0f, 1.0f, 4.0f, 1.0f, 6.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
11.0f, 11.0f, 11.0f, 1.0f, 3.0f, 1.0f, 5.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
12.0f, 12.0f, 12.0f, 2.0f, 1.0f, 4.0f, 1.0f, 6.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
13.0f, 13.0f, 13.0f, 1.0f, 3.0f, 1.0f, 5.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
14.0f, 14.0f, 14.0f, 2.0f, 1.0f, 4.0f, 1.0f, 6.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
15.0f, 15.0f, 15.0f, 1.0f, 3.0f, 1.0f, 5.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
16.0f, 16.0f, 16.0f, 2.0f, 1.0f, 4.0f, 1.0f, 6.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f, 3.0f, 1.0f, 5.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
2.0f, 2.0f, 2.0f, 2.0f, 1.0f, 4.0f, 1.0f, 6.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
3.0f, 3.0f, 3.0f, 1.0f, 3.0f, 1.0f, 5.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
4.0f, 4.0f, 4.0f, 2.0f, 1.0f, 4.0f, 1.0f, 6.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
5.0f, 5.0f, 5.0f, 1.0f, 3.0f, 1.0f, 5.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
6.0f, 6.0f, 6.0f, 2.0f, 1.0f, 4.0f, 1.0f, 6.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
7.0f, 7.0f, 7.0f, 1.0f, 3.0f, 1.0f, 5.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
8.0f, 8.0f, 8.0f, 2.0f, 1.0f, 4.0f, 1.0f, 6.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
9.0f, 9.0f, 9.0f, 1.0f, 3.0f, 1.0f, 5.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
10.0f, 10.0f, 10.0f, 2.0f, 1.0f, 4.0f, 1.0f, 6.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
11.0f, 11.0f, 11.0f, 1.0f, 3.0f, 1.0f, 5.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
12.0f, 12.0f, 12.0f, 2.0f, 1.0f, 4.0f, 1.0f, 6.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
13.0f, 13.0f, 13.0f, 1.0f, 3.0f, 1.0f, 5.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
14.0f, 14.0f, 14.0f, 2.0f, 1.0f, 4.0f, 1.0f, 6.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
15.0f, 15.0f, 15.0f, 1.0f, 3.0f, 1.0f, 5.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
16.0f, 16.0f, 16.0f, 2.0f, 1.0f, 4.0f, 1.0f, 6.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f
};
float mask[] =
{
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f
};
// CHECK CHECK CHECK CHECK CHECK
int shared_memory_size = W * W * W;
int block_size = TILE_WIDTH * TILE_WIDTH * TILE_WIDTH;
int max_size = 3 * block_size;
std::cout << "Block Size: " << block_size << " - Shared Memory Size: " << shared_memory_size << " - Max Size: " << max_size << std::endl;
std::cout << "SHARED MEMORY SIZE HAS TO BE SMALLER THAN MAX SIZE IN ORDER TO WORK PROPERLY !!!!!!!";
cudaMalloc((void **)&deviceInputImageData, image_width * image_height * image_depth * sizeof(float));
cudaMalloc((void **)&deviceOutputImageData, image_width * image_height * image_depth * sizeof(float));
cudaMalloc((void **)&deviceMaskData, MASK_WIDTH * MASK_WIDTH * MASK_WIDTH * sizeof(float));
cudaMemcpy(deviceInputImageData, data, image_width * image_height * image_depth * sizeof(float), cudaMemcpyHostToDevice);
cudaMemcpy(deviceMaskData, mask, MASK_WIDTH * MASK_WIDTH * MASK_WIDTH * sizeof(float), cudaMemcpyHostToDevice);
dim3 dimBlock(TILE_WIDTH, TILE_WIDTH, TILE_WIDTH);
dim3 dimGrid((image_width + TILE_WIDTH - 1) / TILE_WIDTH, (image_height + TILE_WIDTH - 1) / TILE_WIDTH, (image_depth + TILE_WIDTH - 1) / TILE_WIDTH);
convolution<<<dimGrid, dimBlock>>>(deviceInputImageData, deviceMaskData, deviceOutputImageData, image_width, image_height, image_depth);
cudaDeviceSynchronize();
cudaMemcpy(data, deviceOutputImageData, image_width * image_height * image_depth * sizeof(float), cudaMemcpyDeviceToHost);
// Print data
for(int i = 0; i < image_width * image_height * image_depth; ++i)
{
if((i % image_width) == 0)
std::cout << std::endl;
if((i % (image_width * image_height)) == 0)
std::cout << std::endl;
std::cout << data[i] << " - ";
}
cudaFree(deviceInputImageData);
cudaFree(deviceOutputImageData);
cudaFree(deviceMaskData);
return 0;
}
When using a TILE_WIDTH of 8, the convolution seems to partially work nicely, since the second and third layers are the same and also the values seem to be correct. In the 3D case, I calculated the destX, destY and destZ indices according to THIS explanation. The second thing that I changed is the if-condition for the second batch loading: if(destZ < W) to use destZ instead of destY.
My question now is what the reason for the incorrect values inside layer 4 and 5 of the output is. I guess I'm missing some understanding on how big the TILE_WIDTH MUST be in order to work properly. From this answer, I created the following check because every thread is supposed to perform at least 2 loads from global to shared memory:
// CHECK CHECK CHECK CHECK CHECK
int shared_memory_size = W * W;
int block_size = TILE_WIDTH * TILE_WIDTH;
int max_size = 2 * block_size;
std::cout << "Block Size: " << block_size << " - Shared Memory Size: " << shared_memory_size << " - Max Size: " << max_size << std::endl;
std::cout << "SHARED MEMORY SIZE HAS TO BE SMALLER THAN MAX SIZE IN ORDER TO WORK PROPERLY !!!!!!!";
Does it also apply in the 3D case, and if so, is it adapted correctly in my 3D check?
Seems like I adapted it correctly, apart from one stupid error:
// Second batch loading
dest = threadIdx.x + (threadIdx.y * TILE_WIDTH) + (threadIdx.z * TILE_WIDTH * TILE_WIDTH) + TILE_WIDTH * TILE_WIDTH;
I forgot one * TILE_WIDTH, so it should be:
// Second batch loading
dest = threadIdx.x + (threadIdx.y * TILE_WIDTH) + (threadIdx.z * TILE_WIDTH * TILE_WIDTH) + TILE_WIDTH * TILE_WIDTH * TILE_WIDTH;
Related
D3D9 CubeMap texture
I am making a texture cubemap, and the image is output on all 6 sides. How to print a split image on 6 sides? I want to make it without using shaders and I want to know a site where I can study directX Are there any sites you can recommend? this is my code. ㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁ struct CUBEVERTEX { float x, y, z; float tu, tv; }; void SkyBox::onInit(float scale) { CUBEVERTEX vertice[] = { {-1.0f, 1.0f, -1.0f, 0.0f, 0.0f }, { 1.0f, 1.0f, -1.0f, 1.0f, 0.0f }, { 1.0f, -1.0f, -1.0f, 1.0f, 1.0f }, { 1.0f, -1.0f, -1.0f, 1.0f, 1.0f }, {-1.0f, -1.0f, -1.0f, 0.0f, 1.0f }, {-1.0f, 1.0f, -1.0f, 0.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 0.0f, 0.0f }, {-1.0f, 1.0f, 1.0f, 1.0f, 0.0f }, {-1.0f, -1.0f, 1.0f, 1.0f, 1.0f }, {-1.0f, -1.0f, 1.0f, 1.0f, 1.0f }, { 1.0f, -1.0f, 1.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 0.0f, 0.0f }, {-1.0f, -1.0f, -1.0f, 0.0f, 0.0f }, { 1.0f, -1.0f, -1.0f, 1.0f, 0.0f }, { 1.0f, -1.0f, 1.0f, 1.0f, 1.0f }, { 1.0f, -1.0f, 1.0f, 1.0f, 1.0f }, {-1.0f, -1.0f, 1.0f, 0.0f, 1.0f }, {-1.0f, -1.0f, -1.0f, 0.0f, 0.0f }, {-1.0f, 1.0f, 1.0f, 0.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f, 0.0f }, { 1.0f, 1.0f, -1.0f, 1.0f, 1.0f }, { 1.0f, 1.0f, -1.0f, 1.0f, 1.0f }, {-1.0f, 1.0f, -1.0f, 0.0f, 1.0f }, {-1.0f, 1.0f, 1.0f, 0.0f, 0.0f }, {-1.0f, 1.0f, 1.0f, 0.0f, 0.0f }, {-1.0f, 1.0f, -1.0f, 1.0f, 0.0f }, {-1.0f, -1.0f, -1.0f, 1.0f, 1.0f }, {-1.0f, -1.0f, -1.0f, 1.0f, 1.0f }, {-1.0f, -1.0f, 1.0f, 0.0f, 1.0f }, {-1.0f, 1.0f, 1.0f, 0.0f, 0.0f }, { 1.0f, 1.0f, -1.0f, 0.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f, 0.0f }, { 1.0f, -1.0f, 1.0f, 1.0f, 1.0f }, { 1.0f, -1.0f, 1.0f, 1.0f, 1.0f }, { 1.0f, -1.0f, -1.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, -1.0f, 0.0f, 0.0f } }; m_pd3dDevice->CreateVertexBuffer(sizeof(vertice), 0, D3DFVF_CUBEVERTEX, D3DPOOL_DEFAULT, &m_pVB, 0); void* pVertice; m_pVB->Lock(0, sizeof(vertice), &pVertice, 0); memcpy(pVertice, vertice, sizeof(vertice)); m_pVB->Unlock(); } void SkyBox::render() { D3DXMATRIX matWorld; D3DXMatrixIdentity(&matWorld); m_pd3dDevice->SetTransform(D3DTS_WORLD, &matWorld); m_pd3dDevice->SetTexture(0, texture); m_pd3dDevice->SetStreamSource(0, m_pVB, 0, sizeof(CUBEVERTEX)); m_pd3dDevice->SetFVF(D3DFVF_CUBEVERTEX); m_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 12); }
Rendering a cubemap directly as a skybox in Direct3D 9 is not achievable, especially with a "no shaders" requirement. In Direct3D 9, you need to create the resource as a cubemap to use in environment scenarios, and then create SIX individual 2D textures to render it as a skybox--which means having two copies of each cubemap face in memory. In Direct3D 10 or later, you can create a resource and then create two shader resource views: One as a cubemap and another resource as a 2D texture array. This results in one copy of each cubemap face in memory. You can then using shaders render the individual faces of the 2D texture array on a skybox. Here's an example implementation using DirectX 12 Skybox that leverages the DirectX Tool Kit for DX12. Same technique will work for Direct3D 11 as long as you require Direct3D Hardware Feature Level 10.0 or better. Unless you are specifically using Windows XP, there's no reason you should learn Direct3D 9 at this point. Direct3D 11 is the 'mainstream' graphics API you should look at. See Microsoft Docs and DirectX Tool Kit.
How to use keyboard and mouse input to navigate a figure
I'm working on a project involving viewing a 3D from different viewpoints using mouse and keyboard input. When I submitted my first draft, I received the following feedback: "Your object did not react to any of the buttons I pressed to change the camera view! The object of this project is to have the user control the camera by being able to change different views but your object didn't give me that ability!" I currently have it coded to zoom in on the object when pressing the up key and out when pressing the down key. The camera view is supposed to move up and down when moving the mouse. I've tried using some previous code that involved the cameraPosition variable, but it does not function properly when utilized in the pressSpecialKey function or in the rendering function. /*Header Inclusions*/ #include <iostream> #include <GL/glew.h> #include <GL/freeglut.h> //GLM Math Header Inclusions #include <glm/glm.hpp> #include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/type_ptr.hpp> //SOIL image loader Inclusion #include "SOIL2/SOIL2.h" using namespace std; //Standard namespace #define WINDOW_TITLE "Final Project: Spoon" //Window title Macro /*Shader program Macro*/ #ifndef GLSL #define GLSL(Version, Source) "#version " #Version "\n" #Source #endif //Global variable declarations int view_state = 1; /*Variable declarations for shader, window size initialization, buffer and array objects*/ GLint spoonShaderProgram, lampShaderProgram, WindowWidth = 800, WindowHeight = 600; GLuint VBO, SpoonVAO, LightVAO, texture; GLfloat cameraSpeed = 0.0005f; //Movement speed per frame //TODO: Remove unnessary code GLchar currentKey; //Will store key pressed GLfloat lastMouseX = 400, lastMouseY = 300; //Locks mouse cursor at the center of the screen GLfloat mouseXOffset, mouseYOffset, yaw = 0.0f, pitch = 0.0f; //mouse offset, yaw, and pitch variables GLfloat sensitivity = 0.5f; //Used for mouse / camera rotation sensitivity bool mouseDetected = true; //Initially true when mouse movement is detected //Global vector declarations glm::vec3 cameraPosition = glm::vec3(-2.0f, 1.0f, 2.0f); //Initial camera position. glm::vec3 CameraUpY = glm::vec3(0.0f, 1.0f, 0.0f); //Temporary y unit vector glm::vec3 CameraForwardZ = glm::vec3(0.0f, 0.0f, -1.0f); //Temporary z unit vector glm::vec3 front; //Temporary z unit vector for mouse //Subject position and scale glm::vec3 spoonPosition(0.0f, 0.0f, 0.0f); glm::vec3 spoonScale(2.0f); //spoon and light color glm::vec3 objectColor(1.0f, 1.0f, 1.0f); glm::vec3 lightColor(1.0f, 1.0f, 1.0f); //Light position and scale glm::vec3 lightPosition(0.5f, 0.5f, 3.0f); glm::vec3 lightScale(0.3f); /*Function prototypes*/ void UResizeWindow(int, int); void URenderGraphics(void); void UCreateShader(void); void UCreateBuffers(void); void pressSpecialKey(int key, int xx, int yy); void UMouseMove(int x, int y); void UGenerateTexture(void); /*Spoon Vertex Shader Course Code*/ const GLchar * spoonVertexShaderSource = GLSL(330, layout (location = 0) in vec3 position; //Vertex data from Vertex Attrib Pointer 0 layout (location = 1) in vec3 normal; //VAP for normals from Vertex Attrib Pointer 1 layout (location = 2) in vec2 textureCoordinate; //Texture vertex data from Vertex Attrib Pointer 2 out vec3 FragmentPos; //For outgoing color / pixels to fragment shader out vec3 Normal; //For outgoing normals to fragment shader out vec2 mobileTextureCoordinate; //Global variables for the transform matrices uniform mat4 model; uniform mat4 view; uniform mat4 projection; void main(){ gl_Position = projection * view * model * vec4(position, 1.0f); //transforms vertices to clip coordinates FragmentPos = vec3(model * vec4(position, 1.0f)); //Gets fragment / pixel position in world space only (exclude view and projection) Normal = mat3(transpose(inverse(model))) * normal; //get normal vectors in world space only and exclude normal translation properties mobileTextureCoordinate = vec2(textureCoordinate.x, 1 - textureCoordinate.y); //flips the texture horizontal } ); /*Spoon Fragment Shader Source Code*/ const GLchar * spoonFragmentShaderSource = GLSL(330, in vec3 FragmentPos; //For incoming fragment position in vec3 Normal; //For incoming normals in vec2 mobileTextureCoordinate; out vec4 spoonColor; //For outgoing spoon color to the GPU //Uniform / Global variables for object color, light color, light position, and camera/view position uniform vec3 lightColor; uniform vec3 lightPos; uniform vec3 viewPosition; uniform sampler2D uTexture; //Useful when working with multiple textures void main(){ /*Phong lighting model calculations to generate ambient, diffuse, and specular components*/ //Calculate Ambient Lighting float ambientStrength = 0.1f; //Set ambient or global lighting strength vec3 ambient = ambientStrength * lightColor; //Generate ambient light color //Calculate Diffuse Lighting vec3 norm = normalize(Normal); //Normalize vectors to 1 unit vec3 lightDirection = normalize(lightPos - FragmentPos); //Calculate distance (light direction) between light source and fragments/pixels on float impact = max(dot(norm, lightDirection), 0.0); //Calculate diffuse impact by generating dot product of normal and light vec3 diffuse = impact * lightColor; //Generate diffuse light color //Calculate Specular lighting float specularIntensity = 1.6f; //Set specular light strength float highlightSize = 128.0f; //Set specular highlight size vec3 viewDir = normalize(viewPosition - FragmentPos); //Calculate view direction vec3 reflectDir = reflect(-lightDirection, norm); //Calculate reflection vector //Calculate specular component float specularComponent = pow(max(dot(viewDir, reflectDir), 0.0), highlightSize); vec3 specular = specularIntensity * specularComponent * lightColor; //Calculate phong result vec3 objectColor = texture(uTexture, mobileTextureCoordinate).xyz; vec3 phong = (ambient + diffuse) * objectColor + specular; spoonColor = vec4(phong, 1.0f); //Send lighting results to GPU } ); /*Lamp Shader Source Code*/ const GLchar * lampVertexShaderSource = GLSL(330, layout (location = 0) in vec3 position; //VAP position 0 for vertex position data //Uniform / Global variables for the transform matrices uniform mat4 model; uniform mat4 view; uniform mat4 projection; void main() { gl_Position = projection * view *model * vec4(position, 1.0f); //Transforms vertices into clip coordinates } ); /*Lamp Fragment Shader Source Code*/ const GLchar * lampFragmentShaderSource = GLSL(330, out vec4 color; //For outgoing lamp color (smaller spoon) to the GPU void main() { color = vec4(1.0f); //Set color to white (1.0f, 1.0f, 1.0f) with alpha 1.0 } ); /*Main Program*/ int main(int argc, char* argv[]) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA); glutInitWindowSize(WindowWidth, WindowHeight); glutCreateWindow(WINDOW_TITLE); glutReshapeFunc(UResizeWindow); glewExperimental = GL_TRUE; if (glewInit() != GLEW_OK) { std::cout << "Failed to initialize GLEW" << std::endl; return -1; } UCreateShader(); UCreateBuffers(); UGenerateTexture(); glClearColor(0.8f, 0.8f, 0.8f, 1.0f); //Set background color glutDisplayFunc(URenderGraphics); glutSpecialFunc(pressSpecialKey); //Detects key press glutPassiveMotionFunc(UMouseMove); glutMainLoop(); //Destroys Buffer objects once used glDeleteVertexArrays(1, &SpoonVAO); glDeleteVertexArrays(1, &LightVAO); glDeleteBuffers(1, &VBO); return 0; } /*Resizes the window*/ void UResizeWindow(int w, int h) { WindowWidth = w; WindowHeight = h; glViewport(0, 0, WindowWidth, WindowHeight); } /*Renders graphics*/ void URenderGraphics(void) { glEnable(GL_DEPTH_TEST); //Enable z-depth glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //Clears the screen GLint uTextureLoc, lightColorLoc, lightPositionLoc, viewPositionLoc; /*********Use the Spoon Shader to activate the Spoon Vertex Array Object for rendering and transforming*********/ glUseProgram(spoonShaderProgram); glBindVertexArray(SpoonVAO); CameraForwardZ = front; //Replaces camera forward vector with Radians normalized as a unit vector //Transforms the object glm::mat4 model; model = glm::translate(model, glm::vec3(0.0f, 0.0f, 0.0f)); //Place the object at the center of the viewport model = glm::rotate(model, 45.0f, glm:: vec3(0.0, 1.0f, 0.0f)); //Rotate the object 45 degrees on the X model = glm::scale(model, glm::vec3(2.0f, 2.0f, 2.0f)); //Increase the object size by a scale of 2 //Transform the camera glm::mat4 view; view = glm::lookAt(cameraPosition - CameraForwardZ, cameraPosition, CameraUpY); //Creates a perspective projection glm::mat4 projection; if(view_state == 1){ projection = glm::perspective(45.0f, (GLfloat)WindowWidth / (GLfloat)WindowHeight, 0.1f, 100.0f); }else if(view_state == 0){ projection = glm::ortho(-5.0f, 5.0f, -5.0f, 5.0f, 0.1f, 100.0f); } //Reference matrix uniforms from the spoon Shader program GLint modelLoc = glGetUniformLocation(spoonShaderProgram, "model"); GLint viewLoc = glGetUniformLocation(spoonShaderProgram, "view"); GLint projLoc = glGetUniformLocation(spoonShaderProgram, "projection"); //Pass matrix data to the spoon Shader program's matrix uniforms glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model)); glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view)); glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection)); //Reference matrix uniforms from the spoon Shader program for the spoon color, light color, light position, and camera position uTextureLoc = glGetUniformLocation(spoonShaderProgram, "uTexture"); lightColorLoc = glGetUniformLocation(spoonShaderProgram, "lightColor"); lightPositionLoc = glGetUniformLocation(spoonShaderProgram, "lightPos"); viewPositionLoc = glGetUniformLocation(spoonShaderProgram, "viewPosition"); //Pass color, light, and camera data to the spoon Shader programs corresponding uniforms glUniform1i(uTextureLoc, 0); // texture unit 0 glUniform3f(lightColorLoc, lightColor.r, lightColor.g, lightColor.b); glUniform3f(lightPositionLoc, lightPosition.x, lightPosition.y, lightPosition.z); glUniform3f(viewPositionLoc, cameraPosition.x, cameraPosition.y, cameraPosition.z); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texture); glDrawArrays(GL_TRIANGLES, 0, 126); //Draw the primitives / spoon glBindVertexArray(0); //Deactivate the spoon Vertex Array Object /***************Use the Lamp Shader and activate the Lamp Vertex Array Object for rendering and transforming ************/ glUseProgram(lampShaderProgram); glBindVertexArray(LightVAO); //Transform the smaller spoon used as a visual cue for the light source model = glm::translate(model, lightPosition); model = glm::scale(model, lightScale); //Reference matrix uniforms from the Lamp Shader program modelLoc = glGetUniformLocation(lampShaderProgram, "model"); viewLoc = glGetUniformLocation(lampShaderProgram, "view"); projLoc = glGetUniformLocation(lampShaderProgram, "projection"); //Pass matrix uniforms from the Lamp Shader Program glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model)); glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view)); glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection)); //Draws the triangles glDrawArrays(GL_TRIANGLES, 0, 126); glBindVertexArray(0); //Deactivate the Vertex Array Object glutPostRedisplay(); glutSwapBuffers(); //Flips the back buffer with the front buffer every frame. Similar to GL Flush } /*Creates the Shader program*/ void UCreateShader() { //Spoon Vertex shader GLint spoonVertexShader = glCreateShader(GL_VERTEX_SHADER); //Create the Vertex shader glShaderSource(spoonVertexShader, 1, &spoonVertexShaderSource, NULL); //Attaches the vertex shader to the source code glCompileShader(spoonVertexShader); //Compiles the Vertex shader //Spoon Fragment shader GLint spoonFragmentShader = glCreateShader(GL_FRAGMENT_SHADER); //Create the Fragment shader glShaderSource(spoonFragmentShader, 1, &spoonFragmentShaderSource, NULL); //Attaches the Fragment shader to the source code glCompileShader(spoonFragmentShader); //Compiles the Fragment shader //Spoon Shader program spoonShaderProgram = glCreateProgram(); //Creates the Shader program and returns an id glAttachShader(spoonShaderProgram, spoonVertexShader); //Attach Vertex shader to the Shader program glAttachShader(spoonShaderProgram, spoonFragmentShader); //Attach Fragment shader to the Shader program glLinkProgram(spoonShaderProgram); //Link Vertex and Fragment shaders to Shader program //Delete the Vertex and Fragment shaders once linked glDeleteShader(spoonVertexShader); glDeleteShader(spoonFragmentShader); //Lamp Vertex shader GLint lampVertexShader = glCreateShader(GL_VERTEX_SHADER); //Creates the Vertex shader glShaderSource(lampVertexShader, 1, &lampVertexShaderSource, NULL); //Attaches the Vertex shader to the source code glCompileShader(lampVertexShader); //Compiles the Vertex shader //Lamp Fragment shader GLint lampFragmentShader = glCreateShader(GL_FRAGMENT_SHADER); //Creates the Fragment shader glShaderSource(lampFragmentShader, 1, &lampFragmentShaderSource, NULL); //Attaches the Fragment shader to the source code glCompileShader(lampFragmentShader); //Compiles the Fragment shader //Lamp Shader Program lampShaderProgram = glCreateProgram(); //Creates the Shader program and returns an id glAttachShader(lampShaderProgram, lampVertexShader); //Attach Vertex shader to the Shader program glAttachShader(lampShaderProgram, lampFragmentShader); //Attach Fragment shader to the Shader program glLinkProgram(lampShaderProgram); //Link Vertex and Fragment shaders to the Shader program //Delete the lamp shaders once linked glDeleteShader(lampVertexShader); glDeleteShader(lampFragmentShader); } void UCreateBuffers() { GLfloat vertices[] = { //Position //Normals //Texture //Point Name //Front of Scoop //Positive Z -0.4f, 0.05f, 0.1f, 0.0f, 0.0f, 1.0f, 0.3f, 1.0f, //Q -0.4f, -0.1f, 0.1f, 0.0f, 0.0f, 1.0f, 0.3f, 0.0f, //R -0.6f, 0.1f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, //U -0.4f, 0.05f, 0.1f, 0.0f, 0.0f, 1.0f, 0.3f, 1.0f, //Q -0.2f, 0.0f, 0.1f, 0.0f, 0.0f, 1.0f, 0.6f, 1.0f, //W -0.4f, -0.1f, 0.1f, 0.0f, 0.0f, 1.0f, 0.3f, 0.0f, //R -0.4f, -0.1f, 0.1f, 0.0f, 0.0f, 1.0f, 0.3f, 0.0f, //R -0.2f, -0.1f, 0.1f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, //A -0.2f, 0.0f, 0.1f, 0.0f, 0.0f, 1.0f, 0.6f, 1.0f, //W -0.2f, 0.0f, 0.1f, 0.0f, 0.0f, 1.0f, 0.6f, 1.0f, //W -0.2f, -0.1f, 0.1f, 0.0f, 0.0f, 1.0f, 0.6f, 0.0f, //A_1 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, //A 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, //A -0.2f, -0.1f, 0.1f, 0.0f, 0.0f, 1.0f, 0.6f, 1.0f, //A_1 0.0f, -0.05f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, //B //Bottom of Scoop Slant //Negative X -0.6f, 0.1f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.6f, //U -0.6f, 0.1f, -0.1f, -1.0f, 0.0f, 0.0f, 0.0f, 0.3f, //V -0.4f, -0.1f, 0.1f, -1.0f, 0.0f, 0.0f, 0.3f, 1.0f, //R -0.4f, -0.1f, 0.1f, -1.0f, 0.0f, 0.0f, 0.3f, 1.0f, //R -0.4f, -0.1f, -0.2f, -1.0f, 0.0f, 0.0f, 0.3f, 0.0f, //T -0.6f, 0.1f, -0.1f, -1.0f, 0.0f, 0.0f, 0.0f, 0.3f, //V //Bottom of Scoop //Negative Y -0.4f, -0.1f, -0.2f, 0.0f, -1.0f, 0.0f, 0.3f, 0.0f, //T -0.4f, -0.1f, 0.1f, 0.0f, -1.0f, 0.0f, 0.3f, 1.0f, //R -0.2f, -0.1f, -0.2f, 0.0f, -1.0f, 0.0f, 0.6f, 0.0f, //B_1 -0.2f, -0.1f, -0.2f, 0.0f, -1.0f, 0.0f, 0.6f, 0.0f, //B_1 -0.4f, -0.1f, 0.1f, 0.0f, -1.0f, 0.0f, 0.3f, 1.0f, //R -0.2f, -0.1f, 0.1f, 0.0f, -1.0f, 0.0f, 0.6f, 1.0f, //A_1 -0.2f, -0.1f, 0.1f, 0.0f, -1.0f, 0.0f, 0.6f, 1.0f, //A_1 -0.2f, -0.1f, -0.2f, 0.0f, -1.0f, 0.0f, 0.3f, 0.0f, //B_1 0.0f, -0.05f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.6f, //B -0.2f, -0.1f, -0.2f, 0.0f, -1.0f, 0.0f, 0.6f, 0.0f, //B_1 0.0f, -0.05f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.6f, //B 0.0f, -0.05f, -0.1f, 0.0f, -1.0f, 0.0f, 1.0f, 0.3f, //D //Back of Scoop //Negative Z -0.6f, 0.1f, -0.1f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, //V -0.4f, 0.05f, -0.2f, 0.0f, 0.0f, -1.0f, 0.3f, 1.0f, //S -0.4f, -0.1f, -0.2f, 0.0f, 0.0f, -1.0f, 0.3f, 0.0f, //T -0.4f, 0.05f, -0.2f, 0.0f, 0.0f, -1.0f, 0.3f, 1.0f, //S -0.4f, -0.1f, -0.2f, 0.0f, 0.0f, -1.0f, 0.3f, 0.0f, //T -0.2f, -0.1f, -0.2f, 0.0f, 0.0f, -1.0f, 0.6f, 0.0f, //B_1 -0.4f, 0.05f, -0.2f, 0.0f, 0.0f, -1.0f, 0.3f, 1.0f, //S -0.2f, -0.1f, -0.2f, 0.0f, 0.0f, -1.0f, 0.6f, 0.0f, //B_1 -0.2f, 0.0f, -0.2f, 0.0f, 0.0f, -1.0f, 0.6f, 1.0f, //Z -0.2f, 0.0f, -0.2f, 0.0f, 0.0f, -1.0f, 0.6f, 1.0f, //Z -0.2f, -0.1f, -0.2f, 0.0f, 0.0f, -1.0f, 0.6f, 0.0f, //B_1 0.0f, 0.0f, -0.1f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, //C 0.0f, 0.0f, -0.1f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, //C -0.2f, -0.1f, -0.2f, 0.0f, 0.0f, -1.0f, 0.6f, 0.0f, //B_1 0.0f, -0.05f, -0.1f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, //D //Top of Scoop //Positive Y -0.6f, 0.1f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.3f, //U -0.6f, 0.1f, -0.1f, 0.0f, 1.0f, 0.0f, 0.0f, 0.6f, //V -0.4f, 0.05f, -0.2f, 0.0f, 1.0f, 0.0f, 0.3f, 1.0f, //S -0.6f, 0.1f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.3f, //U -0.4f, 0.05f, -0.2f, 0.0f, 1.0f, 0.0f, 0.3f, 1.0f, //S -0.4f, 0.05f, 0.1f, 0.0f, 1.0f, 0.0f, 0.3f, 0.0f, //Q -0.4f, 0.05f, -0.2f, 0.0f, 1.0f, 0.0f, 0.3f, 1.0f, //S -0.4f, 0.05f, 0.1f, 0.0f, 1.0f, 0.0f, 0.3f, 0.0f, //Q -0.2f, 0.0f, -0.2f, 0.0f, 1.0f, 0.0f, 0.6f, 1.0f, //Z -0.4f, 0.05f, 0.1f, 0.0f, 1.0f, 0.0f, 0.3f, 0.0f, //Q -0.2f, 0.0f, -0.2f, 0.0f, 1.0f, 0.0f, 0.6f, 1.0f, //Z -0.2f, 0.0f, 0.1f, 0.0f, 1.0f, 0.0f, 0.6f, 0.0f, //W -0.2f, 0.0f, 0.1f, 0.0f, 1.0f, 0.0f, 0.6f, 0.0f, //W -0.2f, 0.0f, -0.2f, 0.0f, 1.0f, 0.0f, 0.6f, 1.0f, //Z 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.3f, //A -0.2f, 0.0f, -0.2f, 0.0f, 1.0f, 0.0f, 0.6f, 1.0f, //Z 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.3f, //A 0.0f, 0.0f, -0.1f, 0.0f, 1.0f, 0.0f, 1.0f, 0.6f, //C //Front of Handle //Positive Z 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.1f, //A 0.0f, -0.05f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, //B 0.6f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, //E 0.6f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, //E 0.0f, -0.05f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, //B 0.6f, -0.1f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, //F //Bottom of Handle //Negative Y 0.0f, -0.05f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, //B 0.0f, -0.05f, -0.1f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, //D 0.6f, -0.1f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f, //F 0.0f, -0.05f, -0.1f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, //D 0.6f, -0.1f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f, //F 0.6f, -0.1f, -0.1f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, //H //Back of Handle //Negative Z 0.0f, 0.0f, -0.1f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, //C 0.0f, -0.05f, -0.1f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, //D 0.6f, 0.0f, -0.1f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, //G 0.0f, -0.05f, -0.1f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, //D 0.6f, 0.0f, -0.1f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, //G 0.6f, -0.1f, -0.1f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, //H //Top of Handle //Positive Y 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, //A 0.0f, 0.0f, -0.1f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, //C 0.6f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, //E 0.0f, 0.0f, -0.1f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, //C 0.6f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, //E 0.6f, 0.0f, -0.1f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, //G //Grip Connection //Negative X 0.6f, 0.0f, 0.1f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, //I 0.6f, 0.0f, -0.2f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, //J 0.6f, -0.1f, 0.1f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, //K 0.6f, 0.0f, -0.2f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, //J 0.6f, -0.1f, 0.1f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, //K 0.6f, -0.1f, -0.2f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, //L //Front to Grip //Positive Z 0.6f, 0.0f, 0.1f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, //I 1.0f, 0.0f, 0.05f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, //M 0.6f, -0.1f, 0.1f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, //K 1.0f, 0.0f, 0.05f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, //M 0.6f, -0.1f, 0.1f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, //K 1.0f, -0.1f, 0.05f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, //N //Bottom to Grip //Negative Y 0.6f, -0.1f, 0.1f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, //K 1.0f, -0.1f, 0.05f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, //N 0.6f, -0.1f, -0.2f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, //L 1.0f, -0.1f, 0.05f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, //N 0.6f, -0.1f, -0.2f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, //L 1.0f, -0.1f, -0.15f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f, //P //Back to Grip //Negative Z 0.6f, 0.0f, -0.2f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, //J 0.6f, -0.1f, -0.2f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, //L 1.0f, 0.0f, -0.15f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, //O 0.6f, -0.1f, -0.2f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, //L 1.0f, 0.0f, -0.15f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, //O 1.0f, -0.1f, -0.15f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, //P //Top to Grip //Positive Y 1.0f, 0.0f, -0.15f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, //O 1.0f, 0.0f, 0.05f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, //M 0.6f, 0.0f, -0.2f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, //J 1.0f, 0.0f, 0.05f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0, //M 0.6f, 0.0f, -0.2f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, //J 0.6f, 0.0f, 0.1f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, //I //Base of Grip //Positive X 1.0f, 0.0f, 0.05f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, //M 1.0f, -0.1f, 0.05f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, //N 1.0f, 0.0f, -0.15f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, //O 1.0f, -0.1f, 0.05f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, //N 1.0f, 0.0f, -0.15f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, //O 1.0f, -0.1f, -0.15f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f //P }; //Generate buffer ids glGenVertexArrays(1, &SpoonVAO); glGenBuffers(1, &VBO); //Activate the Vertex Array Object before binding and setting any VBOs and Vertex Attribute Pointers. glBindVertexArray(SpoonVAO); //Activate the VBO glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); //Copy vertices to VBO //Set attribute pointer 0 to hold position data glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0); glEnableVertexAttribArray(0); //Enables vertex attribute //Set attribute pointer 1 to hold Normal data glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat))); glEnableVertexAttribArray(1); //Enables vertex attribute //Set attribute pointer 2 to hold Texture coordinate data glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat))); glEnableVertexAttribArray(2); glBindVertexArray(0); //Deactivate the Spoon VAO which is good practice } void pressSpecialKey(int key, int xx, int yy) { switch(key){ //Zoom object in case GLUT_KEY_UP: front.x += 0.1f; front.y += 0.1f; front.z += 0.1f; break; //Zoom object out case GLUT_KEY_DOWN: front.x -= 0.1f; front.y -= 0.1f; front.z -= 0.1f; break; //Change view to orthogonal state case GLUT_KEY_LEFT: view_state = 0; break; //Change view to perspective state case GLUT_KEY_RIGHT: view_state = 1; break; } } /*Implements the UMouseMove function*/ void UMouseMove(int x, int y) { //Immediately replaces center locked coordinated with new mouse coordinates if(mouseDetected) { lastMouseX = x; lastMouseY = y; mouseDetected = false; } //Gets the direction the mouse was moved in x and y mouseXOffset = x - lastMouseX; mouseYOffset = lastMouseY - y; //Inverted Y //Updates with new mouse coordinates lastMouseX = x; lastMouseY = y; //Applies sensitivity to mouse direction mouseXOffset *= sensitivity; mouseYOffset *= sensitivity; //Accumulates the yaw and pitch variables yaw += mouseXOffset; pitch += mouseYOffset; //Maintains a 90 degree pitch for gimbal lock if(pitch > 89.0f) pitch = 89.0f; if(pitch < -89.0f) pitch = -89.0f; //Converts mouse coordinates / degrees into Radians, then to vectors front.x = cos(glm::radians(pitch)) * cos(glm::radians(yaw)); front.y = sin(glm::radians(pitch)); front.z = cos(glm::radians(pitch)) * sin(glm::radians(yaw)); } /*Generate and load the texture*/ void UGenerateTexture(){ glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); int width, height; unsigned char* image = SOIL_load_image("spoon.jpg", &width, &height, 0, SOIL_LOAD_RGB); //Loads texture file glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image); glGenerateMipmap(GL_TEXTURE_2D); SOIL_free_image_data(image); glBindTexture(GL_TEXTURE_2D, 0); //Unbind the texture } Expected: Spoon in center of the screen, mousemovement changes the camera view (horizontally and vertically), up arrow causes camera to zoom in, and down arrow causes camera to zoom out. Actual: Spoon not in center. Mousemovement causes the object to move (horizontally and vertically). Arrows not detected (?).
Zooming at perspective projection can be achieved by shifting the the camera position along the line of sight: void pressSpecialKey(int key, int xx, int yy) { switch(key){ case GLUT_KEY_UP: cameraPosition += front * 0.1f; break; case GLUT_KEY_DOWN: cameraPosition -= front * 0.1f; break; // [...] } or by changing the field of view angle: float fov_angle = 45.0f; projection = glm::perspective(glm::radians(fov_angle), (GLfloat)WindowWidth / (GLfloat)WindowHeight, 0.1f, 100.0f); void pressSpecialKey(int key, int xx, int yy) { switch(key){ case GLUT_KEY_UP: fov_angle -= 0.1f; break; case GLUT_KEY_DOWN: fov_angle += 0.1f; break; // [...] } If you want to keep the spoon in the center of the view ant to orbit around the spoon, then you've to change the camera position according to the viewing direction: void UMouseMove(int x, int y) { // [...] cameraPosition = - front * glm::length( cameraPosition ); } The matrices of the OpenGL Mathematics (GLM) have to be initialized. An identity matrix can be initialized by the single parameter 1.0: e.g. glm::mat4 model(1.0f); The angles which are passed to the OpenGL Mathematics (GLM) library functions have to be set in radians rather than degrees. (In glm version 0.9.4 or less this was different). glm::perspective(): LM_FUNC_DECL tmat4x4<T, defaultp> glm::perspective(T fovy, T aspect, T near, T far) Creates a matrix for a symetric perspective-view frustum based on the default handedness. Parameters fovy Specifies the field of view angle in the y direction. Expressed in radians. glm::rotate() GLM_FUNC_DECL mat<4, 4, T, Q> glm::rotate (mat< 4, 4, T, Q > const & m, T angle, vec<3, T, Q> const & axis) Builds a rotation 4 * 4 matrix created from an axis vector and an angle. Parameters angle Rotation angle expressed in radians. Initialize the matrices and use glm::radians() to convert from degree to radians: //Transforms the object glm::mat4 model(1.0f); // <--- init model = glm::translate(model, glm::vec3(0.0f, 0.0f, 0.0f)); //Place the object at the center of the viewport // model = glm::rotate(model, 45.0f, glm:: vec3(0.0, 1.0f, 0.0f)); model = glm::rotate(model, glm::radians(45.0f), glm:: vec3(0.0, 1.0f, 0.0f)); model = glm::scale(model, glm::vec3(2.0f, 2.0f, 2.0f)); //Increase the object size by a scale of 2 //Transform the camera glm::mat4 view(1.0f); // <--- init view = glm::lookAt(cameraPosition - CameraForwardZ, cameraPosition, CameraUpY); //Creates a perspective projection glm::mat4 projection(1.0f); // <--- init if(view_state == 1){ // projection = glm::perspective(45.0f, (GLfloat)WindowWidth / (GLfloat)WindowHeight, 0.1f, 100.0f); projection = glm::perspective(glm::radians(45.0f), (GLfloat)WindowWidth / (GLfloat)WindowHeight, 0.1f, 100.0f); } else if(view_state == 0){ projection = glm::ortho(-5.0f, 5.0f, -5.0f, 5.0f, 0.1f, 100.0f); }
How to rotate Cubemap face without memory copy in OpenGL?
Update for the question: In the prior question description, I had made several serious mistakes which made the question very hard to understand and to solve. Now I will share my newest code that works. My prior description about the direction of each face was wrong. The correct direction is as follows: The right face is rotated 90 degrees clockwise, and the top face is rotated 180 degrees clockwise. So when setting up the texture coordinates for the right face which is composed of two triangles (3-7-8 and 8-4-3), we need to rotate the face in the 90 degrees counter clockwise, so 3 will use 7's coordinate, 7 -> 8, 8 -> 4, 4 -> 3. When setting up the texture coordinates for the top face which is composed of two triangles(1-4-8 and 8-6-1), we need to rotate the face in 90 degrees counter clockwise, so 1 will use 8's coordinate, 4 -> 6, 8 -> 1, 6 -> 4. The code that works: bool setupCoordinates() { this->vertexCount = 36; float skyboxVertices[] = { // positions // back -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, // Left -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, // Right 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, // Front -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, // Top -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, // Bottom -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f }; float skyboxTextures[] = { // positions // Back same as skyboxVertices -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, // Left same as skyboxVertices -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, // Right rotate in 90 ccw 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, // Front same as skyboxVertices -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, // Top rotate in 180 ccw 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, // Bottom same as skyboxVertices -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f }; glGenVertexArrays(1, &sceneVAO); glBindVertexArray(sceneVAO); glGenBuffers(1, &sceneVertexBuffer); glBindBuffer(GL_ARRAY_BUFFER, sceneVertexBuffer); glBufferData(GL_ARRAY_BUFFER, sizeof(skyboxVertices), &skyboxVertices, GL_STATIC_DRAW); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); glGenBuffers(1, &sceneUVBuffer); glBindBuffer(GL_ARRAY_BUFFER, sceneUVBuffer); glBufferData(GL_ARRAY_BUFFER, sizeof(skyboxTextures), &skyboxTextures, GL_STATIC_DRAW); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void *)0); glBindVertexArray(0); return true; } void drawFrame() { glBindTexture(GL_TEXTURE_CUBE_MAP, sceneTextureID); glPixelStorei(GL_UNPACK_ROW_LENGTH, videoFrameWidth); int width = videoFrameWidth / 3; int height = width; // back glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB, width, width, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData); // left glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); glPixelStorei(GL_UNPACK_SKIP_PIXELS, width); glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGB, width, width, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData); // front glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); glPixelStorei(GL_UNPACK_SKIP_PIXELS, width * 2); glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGB, width, width, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData); // bottom glPixelStorei(GL_UNPACK_SKIP_ROWS, width); glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGB, width, width, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData); // right glPixelStorei(GL_UNPACK_SKIP_ROWS, width); glPixelStorei(GL_UNPACK_SKIP_PIXELS, width); glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGB,width,width,0,GL_RGB,GL_UNSIGNED_BYTE, textureData); // top glPixelStorei(GL_UNPACK_SKIP_ROWS, width); glPixelStorei(GL_UNPACK_SKIP_PIXELS, width * 2); glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB, width, width, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData); } ------------------------------------------------Original question------------------------------------------------ I have a 360 video which is in cubemap3x2 format, and I want to render it using cubemap texture in OpenGL. However, the back and the top face of the cube, are rotated in different directions. The back face is rotated 90 degrees clockwise, and the top face is rotated 180 degrees clockwise. Now I can render the cubemap correctly by memory copy, but I wonder if there is a way to avoid this by using OpenGL's builtin capability? The frame that I need to render: The vertex shader: #version 410 core uniform mat4 matrix; out vec3 TexCoords; layout(location = 0) in vec4 position; layout(location = 1) in vec3 textureIn; void main() { TexCoords = textureIn; gl_Position = matrix * position; } The fragment shader: #version 410 core varying vec3 TexCoords; uniform samplerCube mytexture; void main() { gl_FragColor = texture(mytexture, TexCoords); } The code that I use to render: void Player::SetupScene() { this->m_sceneVertexCount = 36; float skyboxVertices[] = { // positions // Back -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, // Left -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, // Right 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, // Front -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, // Top -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, // Bottom -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f }; float skyboxTextures[] = { // positions // Back -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, // Left -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, // Right 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, // Front -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, // Top -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, // Bottom -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f }; glGenVertexArrays(1, &m_SceneVAO); glBindVertexArray(m_SceneVAO); glGenBuffers(1, &m_sceneVertBuffer); glBindBuffer(GL_ARRAY_BUFFER, m_sceneVertBuffer); glBufferData(GL_ARRAY_BUFFER, sizeof(skyboxVertices), &skyboxVertices, GL_STATIC_DRAW); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void *)0); glGenBuffers(1, &m_sceneTexBuffer); glBindBuffer(GL_ARRAY_BUFFER, m_sceneTexBuffer); glBufferData(GL_ARRAY_BUFFER, sizeof(skyboxTextures), &skyboxTextures, GL_STATIC_DRAW); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void *)0); glBindVertexArray(0); } void Player::SetupTexture(unsigned char *textureData) { int width = frameWidth / 3; glPixelStorei(GL_UNPACK_ROW_LENGTH, frameWidth); glBindTexture(GL_TEXTURE_CUBE_MAP, m_sceneTextureID); // Render left face glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB, width, width, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData); // Render front face glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); glPixelStorei(GL_UNPACK_SKIP_PIXELS, width); glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGB, width, width, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData); // Render right face glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); glPixelStorei(GL_UNPACK_SKIP_PIXELS, width * 2); glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGB, width, width, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData); // Render bottom face glPixelStorei(GL_UNPACK_SKIP_ROWS, width); glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGB, width, width, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData); // Rotate the back face 90 degrees counter clockwise uint8_t *start = textureData + rowLength * height * 3 + width * 3; for (int j = 0; j < height; j++) { for (int i = 0; i < width; i++) { m_pRightFaceBuffer[((width - 1 - i) * width + j) * 3 + 0] = *(start + i * 3 + 0); m_pRightFaceBuffer[((width - 1 - i) * width + j) * 3 + 1] = *(start + i * 3 + 1); m_pRightFaceBuffer[((width - 1 - i) * width + j) * 3 + 2] = *(start + i * 3 + 2); } start += rowLength * 3; } glPixelStorei(GL_UNPACK_ROW_LENGTH, width); glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGB, width, width, 0, GL_RGB, GL_UNSIGNED_BYTE, m_pRightFaceBuffer); // Rotate the bottom face 180 degrees counter clockwise start = textureData + rowLength * height * 3 + width * 2 * 3; for (int j = 0; j < height; j++) { for (int i = 0; i < width; i++) { m_pUpFaceBuffer[((height - 1 - j)*width + (width - i)) * 3 + 0] = *(start + (i) * 3); m_pUpFaceBuffer[((height - 1 - j)*width + (width - i)) * 3 + 1] = *(start + (i) * 3 + 1); m_pUpFaceBuffer[((height - 1 - j)*width + (width - i)) * 3 + 2] = *(start + (i) * 3 + 2); } start += rowLength * 3; } glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB, width, width, 0, GL_RGB, GL_UNSIGNED_BYTE, m_pUpFaceBuffer); } The coordinate that I use to build the cubemap:
You can directly specify the sides of the cubemap by glTexImage2D: glPixelStorei(GL_UNPACK_ROW_LENGTH, frameWidth); // Render left face [...] // Render front face [...] // Render right face [...] // Render bottom face [...] // Render back face glPixelStorei(GL_UNPACK_SKIP_ROWS, width); glPixelStorei(GL_UNPACK_SKIP_PIXELS, width); glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGB, width, width, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData); // Render top face glPixelStorei(GL_UNPACK_SKIP_ROWS, width); glPixelStorei(GL_UNPACK_SKIP_PIXELS, width*2); glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB, width, width, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData); But you have to change the texture coordinates for right and top side. Note you messed up the mapping of the cube map sides to the sides of the cube, but anyway it works: float skyboxTextures[] = { // positions // Back // [...] // Left // [...] // Right 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, // Front // [...] // Top 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, // Bottom // [...] }; See the result: Since the mapping of the sides seems to be messed up, I would prefer to load the sides like this: glPixelStorei(GL_UNPACK_ROW_LENGTH, frameWidth); // Render back face glPixelStorei(GL_UNPACK_SKIP_ROWS, width); glPixelStorei(GL_UNPACK_SKIP_PIXELS, width); glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB, width, width, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData); // Render left face glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGB, width, width, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData); // Render right face glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); glPixelStorei(GL_UNPACK_SKIP_PIXELS, width * 2); glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGB, width, width, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData); // Render front face glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); glPixelStorei(GL_UNPACK_SKIP_PIXELS, width); glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGB, width, width, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData); // Render top face glPixelStorei(GL_UNPACK_SKIP_ROWS, width); glPixelStorei(GL_UNPACK_SKIP_PIXELS, width*2); glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB, width, width, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData); // Render bottom face glPixelStorei(GL_UNPACK_SKIP_ROWS, width); glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGB, width, width, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData); and to use the following texture coordinates: float skyboxTextures[] = { // positions // Back -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, // Left -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, // Right 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, // Front -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, // Top -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, // Bottom 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f }; But note, the y and the z axis are still swapped. I assume this is because the world space up vector in your scene is (0, 1, 0).
OpenGL not making a perfect cube
I am new to openGL and I am trying to learn the basics. I've created the vertices of a cube and their indices for the EBO, it supposed to be a perfect cube, that means, the same length in all sides. However I get this: https://i.gyazo.com/1fb82be379da9b18133a0ab0da8ccbf4.png This kind of a rectangle, istead of a square face. The vertices and the indices are the following: std::vector<GLfloat> _Vertices = { // Positions // Colors // Texture Coords //Front 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, //0 Top Right 0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, //1 Bottom Right -0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, //2 Bottom Left -0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, //3 Top Left //Right 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, //4 Top left 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, //5 Top right 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, //6 Bottom right 0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, //7 Buttom left //Left -0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, //8 Top Right -0.5f, 0.5f,-0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, //9 Buttom Right -0.5f, -0.5f,-0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, //10 Buttom Leff -0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, //11 Top Left //Top -0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, //12 Buttom Left -0.5f, 0.5f,-0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, //13 Top Left 0.5f, 0.5f,-0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, //14 Top Right 0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, //15 Buttom right //Back 0.5f, 0.5f,-0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, //16 Top Right 0.5f, -0.5f,-0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, //17 Bottom Right -0.5f, -0.5f,-0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, //18 Bottom Left -0.5f, 0.5f,-0.5f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, //19 Top Left //Buttom -0.5f, -0.5f,-0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, //20 Top left 0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, //21 Top Right 0.5f, -0.5f,-0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, //22 Buttom Right -0.5f, -0.5f,-0.5f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f //23 Buttom Lrft }; std::vector<GLuint> Indices = { 0, 1, 2, // Firs square 2, 3, 0, 4, 5, 6, 6, 7, 4, 8, 9, 10, 10, 11, 8, 12, 13, 14, 14, 15, 12, 16, 17, 18, 18, 19, 16, 20, 21, 22, 22, 23, 20 }; Now, if you need a part of the code, please ask in the comment section. Thanks.
Your X and Y coordiantes range from -0.5 to 0.5 but your Z is only -0.5 to 0.0
How can I calculate the vertex normals for my model(house)
I just recently drew a house in my Direct3D11 application and it seems to look ok. But the only problem that I have is calculating the vertex normals for the house. Everytime the light strikes the house, it looks a little awkward, and the worst part is that the light wont even strike the inside of the house. (BTW I am using the spotlight technique to create light). Down below is the vertex buffer that contains the vertices, texture coordinates, and the normals for my poorly drawn model. Can someone show me how to calculate the normals for the house? void Create_Vertex_Buffer_for_House() { D3D11_BUFFER_DESC VertexBufferDesc; D3D11_SUBRESOURCE_DATA VertexBufferData; ZeroMemory(&VertexBufferDesc, sizeof(VertexBufferDesc)); VertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; VertexBufferDesc.ByteWidth = sizeof(Vertex_Buffer) * 34; VertexBufferDesc.Usage = D3D11_USAGE_DEFAULT; VertexBufferDesc.CPUAccessFlags = 0; /* Vertex coordinates, Texture Coordinates, and vertex normals (respectably)*/ Vertex_Buffer Vertices[] = { /* Front wall of the house*/ Vertex_Buffer(-1.0f, -1.0f, 1.0f, 0.0f, 10.0f, -1.0f, -1.0f, 1.0f), Vertex_Buffer(-1.0f, 1.0f, 1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f), Vertex_Buffer(1.0f, 1.0f, 1.0f, 10.0f, 0.0f, 1.0f, 1.0f, 1.0f), Vertex_Buffer(1.0f, -1.0f, 1.0f, 10.0f, 10.0f, 1.0f, -1.0f, 1.0f), /* Front wall of the house*/ Vertex_Buffer(-4.0f, -1.0f, 1.0f, 0.0f, 10.0f, -4.0f, -1.0f, 1.0f), Vertex_Buffer(-4.0f, 1.0f, 1.0f, 0.0f, 0.0f, -4.0f, 1.0f, 1.0f), Vertex_Buffer(-2.0f, 1.0f, 1.0f, 10.0f, 0.0f, -2.0f, 1.0f, 1.0f), Vertex_Buffer(-2.0f, -1.0f, 1.0f, 10.0f, 10.0f, -2.0f, -1.0f, 1.0f), /* Rooftop of house (front)*/ Vertex_Buffer(-4.0f, 1.0f, 1.0f, 0.0f, 10.0f, -4.0f, 1.0f, 1.0f), Vertex_Buffer(-4.0f, 2.5f, -1.0f, 0.0f, 0.0f, -4.0f, 2.5f, -1.0f), Vertex_Buffer(1.0f, 2.5f, -1.0f, 10.0f, 0.0f, 1.0f, 2.5f, -1.0f), Vertex_Buffer(1.0f, 1.0f, 1.0f, 10.0f, 10.0f, 1.0f, 1.0f, 1.0f), /* Rooftop of the house(back)*/ Vertex_Buffer(-4.0f, 2.5f, -1.0f, 0.0f, 10.0f, -4.0f, 2.5f, 1.0f), Vertex_Buffer(-4.0f, 1.0f, -3.0f, 0.0f, 0.0f, -4.0f, 2.5f, -3.0f), Vertex_Buffer(1.0f, 1.0f, -3.0f, 10.0f, 0.0f, 1.0f, 1.0f, -3.0f), Vertex_Buffer(1.0f, 2.5f, -1.0f, 10.0f, 10.0f, 1.0f, 2.5f, -1.0f), /* Right wall of the house*/ Vertex_Buffer(1.0f, -1.0f, 1.0f, 0.0f, 10.0f, 1.0f, -1.0f, 1.0f), Vertex_Buffer(1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f), Vertex_Buffer(1.0f, 1.0f, -3.0f, 10.0f, 0.0f, 1.0f, 1.0f, -3.0f), Vertex_Buffer(1.0f, -1.0f, -3.0f, 10.0f, 10.0f, 1.0f, -1.0f, -3.0f), /* right wall of the house(small triangle strip)*/ Vertex_Buffer(1.0f, 1.0f, 1.0f, 0.0f, 10.0f, 1.0f, 1.0f, 1.0f), Vertex_Buffer(1.0f, 2.5f, -1.0f, 0.0f, 0.0f, 1.0f, 2.5f, -1.0f), Vertex_Buffer(1.0f, 1.0f, -3.0f, 10.0f, 0.0f, 1.0f, 1.0f, -3.0f), /* Left wall of the house*/ Vertex_Buffer(-4.0f, -1.0f, -3.0f, 0.0f, 10.0f, -4.0f, -1.0f, -3.0f), Vertex_Buffer(-4.0f, 1.0f, -3.0f, 0.0f, 0.0f, -4.0f, 1.0f, -3.0f), Vertex_Buffer(-4.0f, 1.0f, 1.0f, 10.0f, 0.0f, -4.0f, -1.0f, 1.0f), Vertex_Buffer(-4.0f, -1.0f, 1.0f, 10.0f, 10.0f, -4.0f, -1.0f, 1.0f), /* Left wall of the house (triangle strip)*/ Vertex_Buffer(-4.0f, 1.0f, 1.0f, 0.0f, 10.0f, -4.0f, 1.0f, 1.0f), Vertex_Buffer(-4.0f, 2.5f, -1.0f, 0.0f, 0.0f, -4.0f, 2.5f, -1.0f), Vertex_Buffer(-4.0f, 1.0f, -3.0f, 10.0f, 0.0f, -4.0f, 1.0f, -3.0f), /* Back side of the house*/ Vertex_Buffer(-4.0f, -1.0f, -3.0f, 0.0f, 10.0f, -4.0f, -1.0f, -3.0f), Vertex_Buffer(-4.0f, 1.0f, -3.0f, 0.0f, 0.0f, -4.0f, 1.0f, -3.0f), Vertex_Buffer(1.0f, 1.0f, -3.0f, 10.0f, 0.0f, 1.0f, 1.0f, -3.0f), Vertex_Buffer(1.0f, -1.0f, -3.0f, 10.0f, 10.0f, 1.0f, -1.0f, -3.0f), }; ZeroMemory(&VertexBufferData, sizeof(VertexBufferData)); VertexBufferData.pSysMem = Vertices; device->CreateBuffer(&VertexBufferDesc, &VertexBufferData, &HouseVertexBuffer); } I am not sure if this will help, but down below is my method of implementing the spotlight technique in my pixel shader. struct Light { float3 SpotLight_Position; float range; float3 SpotLight_Direction; float cone; float3 attenuation; float3 directional; float4 ambient; float4 diffuse; }; cbuffer Constant_Buffer { float4x4 TRANSFORMEDMATRIX; /* The final transformed matrix */ float4x4 WORLDSPACE; Light LIGHT; }; struct Vertex_Shader_Output { float4 Positions : SV_POSITION; float2 TextureCoord : TEXTURECOORD; float4 WorldSpace : POSITION; float3 normal : NORMAL; }; struct Sky_Vertex_Shader_Output { float4 Positions : SV_POSITION; float3 TextureCoord : TEXTURECOORD; }; Texture2D Texture; /* Shader Resource for Pixel Shader*/ SamplerState Sampler; /* Shader Resource for Pixel Shader*/ /* PIXEL SHADER THAT WILL BE USED TO CREATE THE FLASH LIGHT*/ float4 Pixelshader(Vertex_Shader_Output input) : SV_TARGET { float4 TextureFormat; float3 lightToPixelVector; float3 finalAmbient; float HowMuchLight; float distance; float3 FinalColor = float3 (0.0f, 0.0f, 0.0f); /* Sampling the texture and storing the format into an object*/ TextureFormat = Texture.Sample(Sampler, input.TextureCoord); /* Scaling the normal vector to a unit length*/ input.normal = normalize(input.normal); /* Creating a vector between the light source and the pixel positions of every object*/ lightToPixelVector = LIGHT.SpotLight_Position - input.WorldSpace; /* Getting the actual distance between the light source and the pixel position*/ distance = length(lightToPixelVector); /* Adding the ambient and the colors of the texture*/ finalAmbient = TextureFormat * LIGHT.ambient; /* If the pixel is too far from the light source*/ if (distance > LIGHT.range) { /* Return the objects color without the light source*/ return float4(finalAmbient, TextureFormat.a); } /* Normalizing the vector to make sure its a unit length*/ lightToPixelVector = normalize(lightToPixelVector); /* Getting the angle between the light source and the vertex normal to see how much light that pixel will receive*/ HowMuchLight = dot(lightToPixelVector, input.normal); if (HowMuchLight > 0.0f) { /* Adding the diffuse and colors of the texture to make the final color*/ FinalColor += TextureFormat * LIGHT.diffuse; /* Calculating the attenuation for the Final Color*/ FinalColor /= (LIGHT.attenuation[0] + (LIGHT.attenuation[1] * distance)) + (LIGHT.attenuation[2] * (distance * distance)); /* */ FinalColor *= pow(max(dot(-lightToPixelVector, LIGHT.SpotLight_Direction), 0.0f), LIGHT.cone); } FinalColor = saturate(FinalColor + finalAmbient); /* Returning the final colors of the texture and the alpha value*/ return float4(FinalColor, TextureFormat.a); }