void GOcean::CreateFresnelMap(ID3D11Device* pd3dDevice) { float SkyBlending = 16.0f; DWORD* buffer = new DWORD[FRESNEL_TEX_SIZE]; for (int i = 0; i < FRESNEL_TEX_SIZE; i++) { float cos_a = i / (FLOAT)FRESNEL_TEX_SIZE; // Using water's refraction index 1.33 DWORD fresnel = (DWORD)(D3DXFresnelTerm(cos_a, 1.33f) * 255); DWORD sky_blend = (DWORD)(powf(1 / (1 + cos_a), SkyBlending) * 255); buffer[i] = (sky_blend << 8) | fresnel; } D3D11_TEXTURE1D_DESC tex_desc; tex_desc.Width = FRESNEL_TEX_SIZE; tex_desc.MipLevels = 1; tex_desc.ArraySize = 1; tex_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; tex_desc.Usage = D3D11_USAGE_IMMUTABLE; tex_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; tex_desc.CPUAccessFlags = 0; tex_desc.MiscFlags = 0; D3D11_SUBRESOURCE_DATA init_data; init_data.pSysMem = buffer; init_data.SysMemPitch = 0; init_data.SysMemSlicePitch = 0; pd3dDevice->CreateTexture1D(&tex_desc, &init_data, &FresnelMap); assert(g_pFresnelMap); delete[] buffer; buffer = NULL; // Create shader resource D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc; srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D; srv_desc.Texture1D.MipLevels = 1; srv_desc.Texture1D.MostDetailedMip = 0; pd3dDevice->CreateShaderResourceView(FresnelMap, &srv_desc, &FresnelMapSRV); assert(g_pSRV_Fresnel); }
OceanSurface::OceanSurface(int N, int M, float L_x, float L_z, float A, glm::vec2 _wind, float g, bool _lines, bool _gpu) : N(N), M(M), L_x(L_x), L_z(L_z), A(A), wind(_wind), g(g), lines(_lines), gpu(_gpu) { grid = new surface_vertex[N * M]; // construct wave height field grid init_positions = new vertex_2d[N * M]; grid_tex_cord = new tex_img_coord[N * N]; h_t0 = new complex_number[N * M]; h_t0_cc = new complex_number[N * M]; h_fft = new complex_number[N * M]; dx_fft = new complex_number[N * M]; dz_fft = new complex_number[N * M]; gradient_x = new complex_number[N * M]; gradient_z = new complex_number[N * M]; lambda = -1.0f; // numeric constant for calculating displacement num_indices = 0; num_triangle_indices = 0; indices = new GLuint[(N - 1) * (M - 1) * 6 + 2 * (N + M - 2)]; triangle_indices = new GLuint[(N - 1) * (M - 1) * 6 * 10]; if (gpu) { wind = glm::vec2(wind.y, wind.x); } //fft myFFT = new MyFFT(N, M); // compute shader FFT stuff char *s_name = "compute_shaders/fft_compute.glsl"; if (N == 32) { s_name = "compute_shaders/fft_compute_32.glsl"; } if (N == 64) { s_name = "compute_shaders/fft_compute_64.glsl"; } if (N == 128) { s_name = "compute_shaders/fft_compute_128.glsl"; } if (N == 256) { s_name = "compute_shaders/fft_compute_256.glsl"; } if (N == 512) { s_name = "compute_shaders/fft_compute_512.glsl"; } fft_comp_program = create_comp_program_from_file(s_name); int bits = log2(N * 1.0f); calc_binary_reverse(bits); glGenBuffers(1, &rev_ind_buffer); glBindBuffer(GL_SHADER_STORAGE_BUFFER, rev_ind_buffer); glBufferData(GL_SHADER_STORAGE_BUFFER, N * sizeof(int), binary_reverse, GL_STATIC_DRAW); glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); GLint steps_location = glGetUniformLocation(fft_comp_program, "steps"); fft_column_location = glGetUniformLocation(fft_comp_program, "fft_column"); glUseProgram(fft_comp_program); glUniform1i(steps_location, bits); // texture for inpute height map glGenTextures(1, &texture_H_t); glBindTexture(GL_TEXTURE_2D, texture_H_t); glTexStorage2D(GL_TEXTURE_2D, 1, GL_RG32F, N, N); //glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32F, N, N, 0, GL_RG, GL_FLOAT, 0); /*glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);*/ // texture for output height map per rows glGenTextures(1, &texture_H_fft_t_row); glBindTexture(GL_TEXTURE_2D, texture_H_fft_t_row); glTexStorage2D(GL_TEXTURE_2D, 1, GL_RG32F, N, N); /*glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);*/ // texture for output height map per columns glGenTextures(1, &texture_H_fft_t_col); glBindTexture(GL_TEXTURE_2D, texture_H_fft_t_col); glTexStorage2D(GL_TEXTURE_2D, 1, GL_RG32F, N, N); /*glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);*/ // texture for fft dx glGenTextures(1, &tex_dx_fft_row); glBindTexture(GL_TEXTURE_2D, tex_dx_fft_row); glTexStorage2D(GL_TEXTURE_2D, 1, GL_RG32F, N, N); glGenTextures(1, &tex_dx_fft); glBindTexture(GL_TEXTURE_2D, tex_dx_fft); glTexStorage2D(GL_TEXTURE_2D, 1, GL_RG32F, N, N); // texture for fft dz glGenTextures(1, &tex_dz_fft_row); glBindTexture(GL_TEXTURE_2D, tex_dz_fft_row); glTexStorage2D(GL_TEXTURE_2D, 1, GL_RG32F, N, N); glGenTextures(1, &tex_dz_fft); glBindTexture(GL_TEXTURE_2D, tex_dz_fft); glTexStorage2D(GL_TEXTURE_2D, 1, GL_RG32F, N, N); // texture for fft gradx glGenTextures(1, &tex_gradx_fft_row); glBindTexture(GL_TEXTURE_2D, tex_gradx_fft_row); glTexStorage2D(GL_TEXTURE_2D, 1, GL_RG32F, N, N); glGenTextures(1, &tex_gradx_fft); glBindTexture(GL_TEXTURE_2D, tex_gradx_fft); glTexStorage2D(GL_TEXTURE_2D, 1, GL_RG32F, N, N); // texture for fft gradz glGenTextures(1, &tex_gradz_fft_row); glBindTexture(GL_TEXTURE_2D, tex_gradz_fft_row); glTexStorage2D(GL_TEXTURE_2D, 1, GL_RG32F, N, N); glGenTextures(1, &tex_gradz_fft); glBindTexture(GL_TEXTURE_2D, tex_gradz_fft); glTexStorage2D(GL_TEXTURE_2D, 1, GL_RG32F, N, N); // unbind all textures glBindTexture(GL_TEXTURE_2D, 0); // assign each point its original 3d coordinates for (int i = 0; i < N; i++) for (int j = 0; j < M; j++) { int pos = i * M + j; // one-dimensional pos from linear two-dimensional grid grid_tex_cord[pos] = tex_img_coord(i, j); // precomputer amplitudes at each point h_t0[pos] = h_t_0(i, j); h_t0_cc[pos] = h_t_0(-i, -j).cc(); // we project our N*M grid coordinates to real world L_x*L_z coordinates grid[pos].x = (i - (N >> 1)) * L_x / N; grid[pos].y = 0.0f; // height is 0 grid[pos].z = (j - (M >> 1)) * L_z / M; // save initial positions init_positions[pos].x = grid[pos].x; init_positions[pos].z = grid[pos].z; // construct indices for index drawing if (i != N - 1 && j != M - 1) { indices[num_indices++] = pos; indices[num_indices++] = pos + 1; indices[num_indices++] = pos; indices[num_indices++] = pos + M; indices[num_indices++] = pos; indices[num_indices++] = pos + M + 1; } if (i != N - 1 && j == M - 1) { indices[num_indices++] = pos; indices[num_indices++] = pos + M; } if (i == N - 1 && j != M - 1) { indices[num_indices++] = pos; indices[num_indices++] = pos + 1; } // construct indices for triangle index drawing if (i != N - 1 && j != M - 1) { triangle_indices[num_triangle_indices++] = pos; triangle_indices[num_triangle_indices++] = pos + N + 1; triangle_indices[num_triangle_indices++] = pos + 1; triangle_indices[num_triangle_indices++] = pos; triangle_indices[num_triangle_indices++] = pos + N; triangle_indices[num_triangle_indices++] = pos + N + 1; } } // check that its okay assert(num_indices == (N - 1) * (M - 1) * 6 + 2 * (N + M - 2)); //assert(num_triangle_indices, (N - 1) * (M - 1) * 6); prepare_for_pipeline(); // update height map compute shader program upd_height_program = create_comp_program_from_file("compute_shaders/update_height_map.glsl"); GLint len_location = glGetUniformLocation(upd_height_program, "L");; GLint n_location = glGetUniformLocation(upd_height_program, "N"); total_time_location = glGetUniformLocation(upd_height_program, "totalTime"); glUseProgram(upd_height_program); glUniform1f(len_location, L_x); glUniform1i(n_location, N); glUseProgram(0); // height map textures glGenTextures(1, &texture_H_t0); glGenTextures(1, &texture_H_t0_cc); glBindTexture(GL_TEXTURE_2D, texture_H_t0); glTexStorage2D(GL_TEXTURE_2D, 1, GL_RG32F, N, N); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, N, N, GL_RG, GL_FLOAT, h_t0); glBindTexture(GL_TEXTURE_2D, texture_H_t0_cc); glTexStorage2D(GL_TEXTURE_2D, 1, GL_RG32F, N, N); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, N, N, GL_RG, GL_FLOAT, h_t0_cc); glBindTexture(GL_TEXTURE_2D, 0); // displacement map textures glGenTextures(1, &texture_Dx); glGenTextures(1, &texture_Dz); glBindTexture(GL_TEXTURE_2D, texture_Dx); glTexStorage2D(GL_TEXTURE_2D, 1, GL_RG32F, N, N); glBindTexture(GL_TEXTURE_2D, texture_Dz); glTexStorage2D(GL_TEXTURE_2D, 1, GL_RG32F, N, N); glBindTexture(GL_TEXTURE_2D, 0); // gradient map textures glGenTextures(1, &texture_Gradx); glGenTextures(1, &texture_Gradz); glBindTexture(GL_TEXTURE_2D, texture_Gradx); glTexStorage2D(GL_TEXTURE_2D, 1, GL_RG32F, N, N); glBindTexture(GL_TEXTURE_2D, texture_Gradz); glTexStorage2D(GL_TEXTURE_2D, 1, GL_RG32F, N, N); glBindTexture(GL_TEXTURE_2D, 0); // Fresnel textures int fres_size = 128; float g_SkyBlending = 16.0f; unsigned int *buffer = new unsigned int[fres_size]; for (int i = 0; i < fres_size; i++) { float cos_a = i / (float)fres_size; // Using water's refraction index 1.33 unsigned int fresnel = (unsigned int)(D3DXFresnelTerm(cos_a, 1.33f) * 255); unsigned int sky_blend = (unsigned int)(powf(1 / (1 + cos_a), g_SkyBlending) * 255); buffer[i] = (sky_blend << 8) | fresnel; } glGenTextures(1, &tex_Fresnel); glBindTexture(GL_TEXTURE_1D, tex_Fresnel); glTexStorage1D(GL_TEXTURE_1D, 1, GL_RGBA8, fres_size); glTexSubImage1D(GL_TEXTURE_1D, 0, 0, fres_size, GL_RGBA, GL_UNSIGNED_INT, buffer); const GLfloat border[] = { 1.0f, 1.0f, 1.0f, 1.0f }; glTexParameterfv(GL_TEXTURE_1D, GL_TEXTURE_BORDER_COLOR, border); glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_COMPARE_FUNC, GL_NEVER); glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); glBindTexture(GL_TEXTURE_1D, 0); delete[] buffer; // Reflect cube textures tex_ReflectCube = SOIL_load_OGL_single_cubemap ( "textures/sky_cube.dds", SOIL_DDS_CUBEMAP_FACE_ORDER, SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_MIPMAPS | SOIL_FLAG_DDS_LOAD_DIRECT ); }