21 #include "system/system.h"
22 #include "../../client/client.h"
25 #include <SDL_joystick.h>
26 #include <SDL_gamecontroller.h>
109 static void change_image_layouts(VkImage image,
const VkImageSubresourceRange* subresource_range);
134 const int num_images = 6;
138 VkImageCreateInfo img_info = {
139 .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
145 .imageType = VK_IMAGE_TYPE_2D,
146 .format = VK_FORMAT_R16G16B16A16_SFLOAT,
148 .arrayLayers = num_images,
149 .samples = VK_SAMPLE_COUNT_1_BIT,
150 .tiling = VK_IMAGE_TILING_OPTIMAL,
151 .usage = VK_IMAGE_USAGE_STORAGE_BIT
152 | VK_IMAGE_USAGE_TRANSFER_DST_BIT
153 | VK_IMAGE_USAGE_SAMPLED_BIT,
154 .flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT,
155 .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
157 .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
163 VkMemoryRequirements mem_req;
171 const VkImageSubresourceRange subresource_range = {
172 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
176 .layerCount = num_images,
183 VkImageViewCreateInfo img_view_info = {
184 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
185 .viewType = VK_IMAGE_VIEW_TYPE_CUBE,
186 .format = VK_FORMAT_R16G16B16A16_SFLOAT,
188 .subresourceRange = subresource_range,
190 VK_COMPONENT_SWIZZLE_R,
191 VK_COMPONENT_SWIZZLE_G,
192 VK_COMPONENT_SWIZZLE_B,
193 VK_COMPONENT_SWIZZLE_A,
201 VkDescriptorImageInfo desc_img_info = {
202 .imageLayout = VK_IMAGE_LAYOUT_GENERAL,
207 VkWriteDescriptorSet s = {
208 .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
211 .dstArrayElement = 0,
212 .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
213 .descriptorCount = 1,
214 .pImageInfo = &desc_img_info,
217 vkUpdateDescriptorSets(
qvk.
device, 1, &s, 0, NULL);
220 vkUpdateDescriptorSets(
qvk.
device, 1, &s, 0, NULL);
225 VkDescriptorImageInfo desc_img_info = {
226 .imageLayout = VK_IMAGE_LAYOUT_GENERAL,
230 VkWriteDescriptorSet s = {
231 .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
234 .dstArrayElement = 0,
235 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
236 .descriptorCount = 1,
237 .pImageInfo = &desc_img_info,
240 vkUpdateDescriptorSets(
qvk.
device, 1, &s, 0, NULL);
243 vkUpdateDescriptorSets(
qvk.
device, 1, &s, 0, NULL);
258 VkDescriptorSetLayout desc_set_layouts[] = {
265 VkPushConstantRange push_constant_range = {
266 .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
268 .size =
sizeof(float) * 16,
272 .setLayoutCount =
LENGTH(desc_set_layouts),
273 .pSetLayouts = desc_set_layouts,
274 .pushConstantRangeCount = 1,
275 .pPushConstantRanges = &push_constant_range,
282 VkDescriptorSetLayout desc_set_layouts[] = {
288 .setLayoutCount =
LENGTH(desc_set_layouts),
289 .pSetLayouts = desc_set_layouts,
296 SDL_InitSubSystem(SDL_INIT_JOYSTICK);
300 for (
int i = 0; i < SDL_NumJoysticks(); i++)
302 if (SDL_IsGameController(i))
350 image_t const * albedo_map =
IMG_Find(
"env/planet_albedo.tga", IT_SKIN, IF_SRGB);
351 if (albedo_map != R_NOTEXTURE) {
355 image_t const * normal_map =
IMG_Find(
"env/planet_normal.tga", IT_SKIN, IF_SRGB);
356 if (normal_map != R_NOTEXTURE) {
367 VkComputePipelineCreateInfo pipeline_info = {
368 .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
369 .stage =
SHADER_STAGE(QVK_MOD_PHYSICAL_SKY_COMP, VK_SHADER_STAGE_COMPUTE_BIT),
377 VkComputePipelineCreateInfo pipeline_info = {
378 .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
379 .stage =
SHADER_STAGE(QVK_MOD_PHYSICAL_SKY_SPACE_COMP, VK_SHADER_STAGE_COMPUTE_BIT),
387 VkComputePipelineCreateInfo pipeline_info = {
388 .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
389 .stage =
SHADER_STAGE(QVK_MOD_SKY_BUFFER_RESOLVE_COMP, VK_SHADER_STAGE_COMPUTE_BIT),
416 #define BARRIER_COMPUTE(cmd_buf, img) \
418 VkImageSubresourceRange subresource_range = { \
419 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, \
422 .baseArrayLayer = 0, \
425 IMAGE_BARRIER(cmd_buf, \
427 .subresourceRange = subresource_range, \
428 .srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT, \
429 .dstAccessMask = VK_ACCESS_SHADER_READ_BIT, \
430 .oldLayout = VK_IMAGE_LAYOUT_GENERAL, \
431 .newLayout = VK_IMAGE_LAYOUT_GENERAL, \
442 .size = VK_WHOLE_SIZE,
443 .srcAccessMask = VK_ACCESS_UNIFORM_READ_BIT,
444 .dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT
448 0, VK_WHOLE_SIZE, 0);
453 .size = VK_WHOLE_SIZE,
454 .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
455 .dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT
477 VkDescriptorSet desc_sets[] = {
492 vkCmdBindDescriptorSets(cmd_buf, VK_PIPELINE_BIND_POINT_COMPUTE,
494 const int group_size = 16;
495 vkCmdDispatch(cmd_buf,
width / group_size,
height / group_size, 6);
503 .size = VK_WHOLE_SIZE,
504 .srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT,
505 .dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT
509 VkDescriptorSet desc_sets[] = {
514 vkCmdBindPipeline(cmd_buf, VK_PIPELINE_BIND_POINT_COMPUTE,
pipeline_resolve);
515 vkCmdBindDescriptorSets(cmd_buf, VK_PIPELINE_BIND_POINT_COMPUTE,
518 vkCmdDispatch(cmd_buf, 1, 1, 1);
524 .size = VK_WHOLE_SIZE,
525 .srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT,
526 .dstAccessMask = VK_ACCESS_UNIFORM_READ_BIT
540 .subresourceRange = *subresource_range,
542 .dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
543 .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
544 .newLayout = VK_IMAGE_LAYOUT_GENERAL,
554 static int prev_milliseconds = 0;
556 if (!prev_milliseconds)
558 prev_milliseconds = curr_milliseconds;
562 int frame_time = curr_milliseconds - prev_milliseconds;
563 prev_milliseconds = curr_milliseconds;
565 if (frame_time > 1000)
570 float dx = SDL_GameControllerGetAxis(
game_controller,
sun_gamepad->integer == 1 ? SDL_CONTROLLER_AXIS_LEFTX : SDL_CONTROLLER_AXIS_RIGHTX);
571 float dy = SDL_GameControllerGetAxis(
game_controller,
sun_gamepad->integer == 1 ? SDL_CONTROLLER_AXIS_LEFTY : SDL_CONTROLLER_AXIS_RIGHTY);
573 const float deadzone = 8000.f;
574 const float limit = 32768.f - deadzone;
575 dx = powf(max(fabsf(dx) - deadzone, 0.f) / limit, 2.f) * (dx < 0 ? -1.f : 1.f);
576 dy = powf(max(fabsf(dy) - deadzone, 0.f) / limit, 2.f) * (dy < 0 ? -1.f : 1.f);
578 dx *= frame_time * 0.05f;
579 dy *= frame_time * 0.05f;
585 while (azimuth > 360.f) azimuth -= 360.f;
586 while (azimuth < 0.f) azimuth += 360.f;
595 if (elevation > 90.f) elevation = 90.f;
596 if (elevation < -90.f) elevation = -90.f;
622 static uint16_t skyIndex = -1;
634 memset(light, 0,
sizeof(*light));
647 float azimuth, elevation;
649 static float start_time = 0.0f, sun_animate_changed = 0.0f;
662 struct tm* local_time;
669 float time_of_day = local_time->tm_hour + local_time->tm_min / 60.f;
672 else if (local_time->tm_isdst)
714 float elapsed = (time - start_time) * 1000.f *
sun_animate->value;
716 azimuth = fmod(
sun_azimuth->value + elapsed / (24.f * 60.f * 60.f), 360.0f);
718 float e = fmod(
sun_elevation->value + elapsed / (60.f * 60.f), 360.0f);
720 elevation = -(360.f - e);
723 elevation = -(e - 180.0f);
724 azimuth = fmod(azimuth + 180.f, 360.f);
728 elevation = 180.0f - e;
729 azimuth = fmod(azimuth + 180.f, 360.f);
733 elevation = max(-90, min(90, elevation));
745 float elevation_rad = elevation * M_PI / 180.0f;
746 float azimuth_rad = azimuth * M_PI / 180.f;
766 vec3_t sun_direction_world = { 0.f };
770 VectorCopy(sun_direction_world, light->
direction);
779 ubo->pt_env_scale = 0.3f;
782 const float min_brightness = -10.f;
783 const float max_brightness = 2.f;
786 ubo->pt_env_scale = exp2f(brightness - 2.f);
794 ubo->sun_solid_angle = 2 * M_PI * (float)(1.0 - cos(light->
angular_size_rad * 0.5));
797 VectorCopy(light->
color, ubo->sun_color);
799 VectorCopy(light->
direction, ubo->sun_direction);
803 VectorSet(ubo->sun_tangent, 1.f, 0.f, 0.f);
804 VectorSet(ubo->sun_bitangent, 0.f, 1.f, 0.f);
809 VectorSet(
up, 0.f, 0.f, 1.f);
810 CrossProduct(light->
direction,
up, ubo->sun_tangent);
812 CrossProduct(light->
direction, ubo->sun_tangent, ubo->sun_bitangent);
833 uint32_t flags = skyDesc->
flags;
841 ubo->physical_sky_flags = flags;
844 vec3_t ground_radiance;
846 VectorScale(ground_radiance, max(0.f, light->
direction_envmap[2]), ground_radiance);
847 VectorVectorScale(ground_radiance, light->
color, ground_radiance);
849 VectorCopy(ground_radiance, ubo->physical_sky_ground_radiance);
859 ubo->sun_visible = light->
visible;
883 static char _rgb[3] = {
'r',
'g',
'b'};
886 for (
int i = 0; i < 3; ++i)
889 snprintf(buff, 32,
"sun_color_%c", _rgb[i]);
952 for (
int i = 0; i < 3; ++i)
971 .sunColor = {1.45f, 1.29f, 1.27f},
972 .sunAngularDiameter = 1.f,
973 .groundAlbedo = {0.3f, 0.15f, 0.14f},
978 .sunColor = {0.315f, 0.137f, 0.033f},
979 .sunAngularDiameter = 5.f,
980 .groundAlbedo = {0.133, 0.101, 0.047},
988 if (index >= 0 && index < q_countof(
skyPresets))
994 static void rotationQuat(vec3_t
const axis,
float radians, vec4_t result)
997 float sinHalfTheta = sinf(0.5f * radians);
998 float cosHalfTheta = cosf(0.5f * radians);
999 result[0] = cosHalfTheta;
1000 result[1] = axis[0] * sinHalfTheta;
1001 result[2] = axis[1] * sinHalfTheta;
1002 result[3] = axis[2] * sinHalfTheta;
1005 static float dotQuat(vec4_t
const q0, vec4_t
const q1)
1007 return q0[0]*q1[0] + q0[1]*q1[1] + q0[2]*q1[2] + q0[3]*q1[3];
1012 float l = sqrtf(
dotQuat(q, q));
1013 for (
int i = 0; i < 4; ++i)
1029 for (
int i = 0; i < 4; ++i)
1033 static void quatMult(vec4_t
const a, vec4_t
const b, vec4_t result)
1035 result[0] = a[0] * b[0] - a[1] * b[1] - a[2] * b[2] - a[3] * b[3];
1036 result[1] = a[0] * b[1] + a[1] * b[0] + a[2] * b[3] - a[3] * b[2];
1037 result[2] = a[0] * b[2] + a[2] * b[0] + a[3] * b[1] - a[1] * b[3];
1038 result[3] = a[0] * b[3] + a[3] * b[0] + a[1] * b[2] - a[2] * b[1];
1043 const float AxialTilt = 23.439f;
1044 const float DaysInYear = 365.25f;
1045 const float SpringEquinoxDay = 79.0f;
1047 float altitudeAtNoon = 90 - LatitudeDegrees + AxialTilt * sinf((DayOfYear - SpringEquinoxDay) / DaysInYear * 2.0f * M_PI);
1048 altitudeAtNoon = altitudeAtNoon * M_PI / 180.f;
1050 float altitudeOfEarthAxis = 180 - LatitudeDegrees;
1051 altitudeOfEarthAxis = altitudeOfEarthAxis * M_PI / 180.f;
1057 vec3_t noonVector = { cosf(altitudeAtNoon), sinf(altitudeAtNoon), 0.0f };
1058 vec3_t earthAxis = { cosf(altitudeOfEarthAxis), sinf(altitudeOfEarthAxis), 0.0f };
1060 float angleFromNoon = (TimeOfDay - 12.0f) / 24.0f * 2.f * M_PI;
1065 vec4_t dayRotationInv = { dayRotation[0], dayRotation[1], dayRotation[2], dayRotation[3] };
1070 vec4_t sunDirection = { 0.0f, 0.0f, 0.0f, 0.0f };
1071 vec4_t noonQuat = { 0.0f, noonVector[0], noonVector[1], noonVector[2] };
1072 quatMult(dayRotationInv, noonQuat, sunDirection);
1073 quatMult(sunDirection, dayRotation, sunDirection);
1076 result[0] = sunDirection[1];
1077 result[1] = sunDirection[3];
1078 result[2] = sunDirection[2];