Definição da função

f <- function(x, y) 300 - 15 * x^2 - 10 * y^2 + 5 * x * y

x <- seq(-5, 5, length.out = 60)
y <- seq(-5, 5, length.out = 60)
z <- outer(x, y, f)

Gráfico interativo (plotly)

# install.packages("plotly")  # se necessário
library(plotly)
library(tidyverse)

plot_ly(x = ~x, y = ~y, z = ~t(z)) %>%
  add_surface(colorscale = "Viridis") %>%
  layout(title = "f(x,y) = 300 - 15x² - 10y² + 5xy",
         scene = list(xaxis = list(title = "x"),
                      yaxis = list(title = "y"),
                      zaxis = list(title = "f(x,y)")))

Curvas de nível

contour(x, y, z, nlevels = 20, xlab = "x", ylab = "y",
        main = "Curvas de nível")
points(0, 0, pch = 19, col = "red")

Adicionando derivadas parciais

f <- function(x, y) 300 - 15 * x^2 - 10 * y^2 + 5 * x * y

x_seq <- seq(-5, 5, length.out = 200)
y_seq <- seq(-6, 6, length.out = 200)

dados <- expand_grid(x = x_seq, y = y_seq) %>%
  mutate(z = f(x, y)) %>% 
  mutate(z = if_else(z>0, z, NA_real_)) #somente valores positivos de z

# Matriz z: linhas = y, colunas = x
z_mat <- dados %>%
  pivot_wider(names_from = x, values_from = z) %>%
  arrange(y) %>%
  select(-y) %>%
  as.matrix()

# Curvas na superfície
curva_x1 <- tibble(x = 1, y = y_seq) %>% mutate(z = f(x, y)) %>% filter(z>0)   # x = 1
curva_y1 <- tibble(x = x_seq, y = 1) %>% mutate(z = f(x, y)) %>% filter(z>0)   # y = 1

# Extensão dos planos: onde f(1, y) > 0 e f(x, 1) > 0
y_lim <- range(curva_x1$y)
x_lim <- range(curva_y1$x)

# Limites verticais dos planos
zmin <- 0   # min(dados$z)
zmax <- 300 # max(dados$z)
# Cores sólidas para os planos
cor_azul     <- list(c(0, 1), c("royalblue", "royalblue"))
cor_vermelha <- list(c(0, 1), c("firebrick", "firebrick"))

plot_ly() %>%
  # Superfície
  add_surface(x = ~x_seq, y = ~y_seq, z = ~z_mat,
              colorscale = "Viridis", opacity = 0.9,
              name = "f(x,y)", showscale = FALSE) %>%
  # Plano x = 1
  add_surface(x = matrix(1, 2, 2),
              y = matrix(c(y_lim[1], y_lim[2], y_lim[1], y_lim[2]), 2, 2),
              z = matrix(c(zmin, zmin, zmax, zmax), 2, 2),
              colorscale = cor_azul, opacity = 0.25,
              showscale = FALSE, name = "plano x = 1") %>%
  # Plano y = 1
  add_surface(x = matrix(c(x_lim[1], x_lim[2], x_lim[1], x_lim[2]), 2, 2),
              y = matrix(1, 2, 2),
              z = matrix(c(zmin, zmin, zmax, zmax), 2, 2),
              colorscale = cor_vermelha, opacity = 0.25,
              showscale = FALSE, name = "plano y = 1") %>%
  # Curva x = 1 sobre a superfície
  add_trace(data = curva_x1, x = ~x, y = ~y, z = ~z,
            type = "scatter3d", mode = "lines",
            line = list(color = "blue", width = 7),
            name = "curva x = 1") %>%
  # Curva y = 1 sobre a superfície
  add_trace(data = curva_y1, x = ~x, y = ~y, z = ~z,
            type = "scatter3d", mode = "lines",
            line = list(color = "red", width = 7),
            name = "curva y = 1") %>%
  layout(
    title = "f(x,y) = 300 - 15x² - 10y² + 5xy",
    scene = list(
      xaxis = list(title = "x"),
      yaxis = list(title = "y"),
      zaxis = list(title = "f(x,y)")
    )
  )