send image data to client

This commit is contained in:
ktyl 2023-02-17 22:55:31 +00:00
parent 8b62cd574d
commit d244c23e2b
3 changed files with 106 additions and 33 deletions

View File

@ -2,22 +2,62 @@
#include "rtweekend.h" #include "rtweekend.h"
// for writing to stdout
#include <iostream> #include <iostream>
void write_colour(std::ostream &out, colour pixel_colour, int samples_per_pixel) // for writing to socket
{ #include <unistd.h>
auto r = pixel_colour.x();
auto g = pixel_colour.y();
auto b = pixel_colour.z();
// divide the colour total by the number of samples and gamme-correct for gamma=2.0 void correct_gamma(colour& pixel_colour, int samples)
auto scale = 1.0 / samples_per_pixel; {
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); r = sqrt(scale * r);
g = sqrt(scale * g); g = sqrt(scale * g);
b = sqrt(scale * b); 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. // write the translated [0,255] value of each colour component.
out << static_cast<int>(256 * clamp(r, 0.0, 0.999)) << ' ' out << static_cast<int>(256 * clamp(r, 0.0, 0.999)) << ' '
<< static_cast<int>(256 * clamp(g, 0.0, 0.999)) << ' ' << static_cast<int>(256 * clamp(g, 0.0, 0.999)) << ' '
<< static_cast<int>(256 * clamp(b, 0.0, 0.999)) << '\n'; << static_cast<int>(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);
int written = write(sockfd, s, len);
if (written < 0)
{
error("ERROR writing colour to socket");
}
}

View File

@ -2,6 +2,13 @@
#include "hittable_list.h" #include "hittable_list.h"
#include "sphere.h" #include "sphere.h"
void error(const char* message)
{
perror(message);
exit(1);
}
#include "colour.h" #include "colour.h"
#include "camera.h" #include "camera.h"
#include "material.h" #include "material.h"
@ -15,9 +22,9 @@
#include <sys/socket.h> #include <sys/socket.h>
#include <netinet/in.h> #include <netinet/in.h>
const double ASPECT_RATIO = 16.0 / 9.0; const double ASPECT_RATIO = 1.0;
const int WIDTH = 1920; const unsigned int WIDTH = 256;
const int HEIGHT = static_cast<int>(WIDTH / ASPECT_RATIO); const unsigned int HEIGHT = static_cast<int>(WIDTH / ASPECT_RATIO);
const int SAMPLES_PER_PIXEL = 8; const int SAMPLES_PER_PIXEL = 8;
const int MAX_DEPTH = 5; const int MAX_DEPTH = 5;
@ -119,12 +126,6 @@ hittable_list random_scene()
return world; return world;
} }
void error(const char* message)
{
perror(message);
exit(1);
}
// file descriptor of the socket we're listening for connections on // file descriptor of the socket we're listening for connections on
// //
// returns fd for the client connection // 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_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(64999); // convert number from host to network byte order 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 // bind the socket
if (bind(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) if (bind(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0)
{ {
@ -185,6 +198,24 @@ void send_message(int sock, const char* message)
printf("SEND %s\n", message); printf("SEND %s\n", message);
} }
void send_image_dimensions(int sock, unsigned int width, unsigned int height)
{
// https://linux.die.net/man/3/htons
width = htonl(width);
height = htonl(height);
int written = write(sock, &width, sizeof(uint32_t));
if (written < 0)
{
error("ERROR writing width");
}
written = write(sock, &height, sizeof(uint32_t));
if (written < 0)
{
error("ERROR writing height");
}
}
int main() int main()
{ {
int sockfd; int sockfd;
@ -192,20 +223,9 @@ int main()
printf("got a connection!\n"); printf("got a connection!\n");
// write a message to the client send_image_dimensions(newsockfd, WIDTH, HEIGHT);
send_message(newsockfd, "hi there!");
// close client socket //std::cout << "P3\n" << WIDTH << ' ' << HEIGHT << "\n255\n";
close(newsockfd);
printf("closed client connection\n");
// close listening socket
close(sockfd);
// exit after all our connections are closed
exit(0);
std::cout << "P3\n" << WIDTH << ' ' << HEIGHT << "\n255\n";
hittable_list world = random_scene(); hittable_list world = random_scene();
@ -234,10 +254,23 @@ int main()
pixel_colour += ray_colour(r, world, MAX_DEPTH); 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;
} }

View File

@ -6,8 +6,8 @@ use rti1w as a base
* [x] client establishes connection * [x] client establishes connection
* [x] send a message to the client * [x] send a message to the client
* [ ] move rendering out of main.cpp * [ ] move rendering out of main.cpp
* [ ] send rendered image data to client * [x] send rendered image data to client
* [ ] form image file on client * [x] form image file on client
* [ ] client sends receiving port to server * [ ] client sends receiving port to server
* [ ] client application sends command to send image * [ ] client application sends command to send image
* [ ] server receives imaging command * [ ] server receives imaging command