From e41d268581dd6e8a5a033a322be6972fe395ef98 Mon Sep 17 00:00:00 2001 From: ktyl Date: Fri, 17 Feb 2023 22:55:31 +0000 Subject: [PATCH] send image data to client --- src/colour.h | 57 +++++++++++++++++++++++++++++++++++++++++++------ src/main.cpp | 60 ++++++++++++++++++++++++++++++++++++---------------- telescope.md | 2 +- 3 files changed, 93 insertions(+), 26 deletions(-) diff --git a/src/colour.h b/src/colour.h index 1347b08..31de54b 100755 --- a/src/colour.h +++ b/src/colour.h @@ -2,22 +2,65 @@ #include "rtweekend.h" +// for writing to stdout #include -void write_colour(std::ostream &out, colour pixel_colour, int samples_per_pixel) -{ - auto r = pixel_colour.x(); - auto g = pixel_colour.y(); - auto b = pixel_colour.z(); +// for writing to socket +#include - // divide the colour total by the number of samples and gamme-correct for gamma=2.0 - auto scale = 1.0 / samples_per_pixel; +void correct_gamma(colour& pixel_colour, int samples) +{ + double r = pixel_colour.x(); + double g = pixel_colour.y(); + double b = pixel_colour.z(); + + // divide the colour total by the number of samples and gamma-correct for gamma=2.0 + auto scale = 1.0 / samples; r = sqrt(scale * r); g = sqrt(scale * g); b = sqrt(scale * b); + + pixel_colour = colour(r, g, b); +} + +void write_colour_to_stream(std::ostream &out, colour pixel_colour, int samples_per_pixel) +{ + correct_gamma(pixel_colour, samples_per_pixel); + + auto r = pixel_colour.x(); + auto g = pixel_colour.y(); + auto b = pixel_colour.z(); // write the translated [0,255] value of each colour component. out << static_cast(256 * clamp(r, 0.0, 0.999)) << ' ' << static_cast(256 * clamp(g, 0.0, 0.999)) << ' ' << static_cast(256 * clamp(b, 0.0, 0.999)) << '\n'; } + +int format_component(double component) +{ + return int(256 * clamp(component, 0.0, 0.999)); +} + +void write_colour_to_socket(int sockfd, colour pixel_colour, int samples_per_pixel) +{ + correct_gamma(pixel_colour, samples_per_pixel); + + + int r = format_component(pixel_colour.x()); + int g = format_component(pixel_colour.y()); + int b = format_component(pixel_colour.z()); + + // pack values + int len = 3; + char s[len]; + sprintf(s, "%c%c%c", r, g, b); + + printf("SEND %x %x %x\n", r, g, b); + + int written = write(sockfd, s, len); + if (written < 0) + { + error("ERROR writing colour to socket"); + } +} diff --git a/src/main.cpp b/src/main.cpp index b1c16cf..a8dca25 100755 --- a/src/main.cpp +++ b/src/main.cpp @@ -2,6 +2,13 @@ #include "hittable_list.h" #include "sphere.h" + +void error(const char* message) +{ + perror(message); + exit(1); +} + #include "colour.h" #include "camera.h" #include "material.h" @@ -15,8 +22,8 @@ #include #include -const double ASPECT_RATIO = 16.0 / 9.0; -const int WIDTH = 1920; +const double ASPECT_RATIO = 1.0; +const int WIDTH = 64; const int HEIGHT = static_cast(WIDTH / ASPECT_RATIO); const int SAMPLES_PER_PIXEL = 8; const int MAX_DEPTH = 5; @@ -119,12 +126,6 @@ hittable_list random_scene() return world; } -void error(const char* message) -{ - perror(message); - exit(1); -} - // file descriptor of the socket we're listening for connections on // // returns fd for the client connection @@ -162,6 +163,18 @@ int wait_for_client(int& sockfd) serv_addr.sin_addr.s_addr = INADDR_ANY; serv_addr.sin_port = htons(64999); // convert number from host to network byte order + // this is a bit of developer QoL so we can iterate more quickly + // TODO: make it possible to disable this debug/release build configuration + const int enable = 1; + if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) < 0) + { + error("ERROR setsockopt(SO_REUSEADDR) failed"); + } + if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, &enable, sizeof(int)) < 0) + { + error("ERROR setsockopt(SO_REUSEPORT) failed"); + } + // bind the socket if (bind(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) { @@ -193,17 +206,15 @@ int main() printf("got a connection!\n"); // write a message to the client - send_message(newsockfd, "hi there!"); + //send_message(newsockfd, "hi there!"); - // close client socket - close(newsockfd); + // write image header + char buf[100]; + sprintf(buf, "P3\n%d %d\n255\n", WIDTH, HEIGHT); + send_message(newsockfd, buf); - printf("closed client connection\n"); + //write_colour_to_socket(newsockfd, colour(.4, .5, .6), 1); - // close listening socket - close(sockfd); - // exit after all our connections are closed - exit(0); std::cout << "P3\n" << WIDTH << ' ' << HEIGHT << "\n255\n"; @@ -234,10 +245,23 @@ int main() pixel_colour += ray_colour(r, world, MAX_DEPTH); } - write_colour(std::cout, pixel_colour, SAMPLES_PER_PIXEL); + //write_colour_to_stream(std::cout, pixel_colour, SAMPLES_PER_PIXEL); + write_colour_to_socket(newsockfd, pixel_colour, SAMPLES_PER_PIXEL); } } - std::cerr << "\nDone." << std::endl; + // close client socket + close(newsockfd); + + printf("closed client connection\n"); + + // close listening socket + close(sockfd); + + printf("closed listening socket\n"); + + printf("done!\n"); + + return 0; } diff --git a/telescope.md b/telescope.md index 3574d23..db2dac8 100644 --- a/telescope.md +++ b/telescope.md @@ -6,7 +6,7 @@ use rti1w as a base * [x] client establishes connection * [x] send a message to the client * [ ] move rendering out of main.cpp -* [ ] send rendered image data to client +* [x] send rendered image data to client * [ ] form image file on client * [ ] client sends receiving port to server * [ ] client application sends command to send image